volksbanker 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in volksbanker.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # Volksbanker
2
+
3
+ Prepares Volksbank's electronic statements for upload to Freeagent.
4
+
5
+
6
+ ## Usage
7
+
8
+ vb STATEMENT > out.csv
9
+
10
+ where STATEMENT is your electronic statement from Volksbank, and `out.csv` is the file you'll upload to Freeagent.
11
+
12
+
13
+ ## Installation
14
+
15
+ gem install volksbanker
16
+
17
+
18
+ ## Intellectual property
19
+
20
+ Copyright 2012 Andrew Stewart, AirBlade Software Ltd.
21
+
22
+ Released under the MIT licence.
23
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib' << 'test'
6
+ t.test_files = FileList['test/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
data/bin/vb ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby-local-exec
2
+
3
+ lib_dir = File.join File.dirname(__FILE__), '..', 'lib'
4
+ $LOAD_PATH.unshift lib_dir
5
+
6
+ require 'volksbanker'
7
+
8
+ Volksbanker::Cli.run ARGV.first
9
+
@@ -0,0 +1,19 @@
1
+ module Volksbanker
2
+
3
+ class AmexLineItem
4
+ DATE_FORMAT = '%d/%m/%Y'
5
+
6
+ attr_reader :amount, :description
7
+
8
+ def initialize(date, amount, description)
9
+ @date = date
10
+ @amount = amount
11
+ @description = description
12
+ end
13
+
14
+ def date
15
+ @date.strftime DATE_FORMAT
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'volksbanker/volksbank_file_reader'
2
+
3
+ module Volksbanker
4
+
5
+ class Cli
6
+ def self.run(volksbank_file)
7
+ reader = VolksbankFileReader.new volksbank_file
8
+ reader.each_line_item do |vli|
9
+ unless vli.currency == 'EUR'
10
+ $stderr.puts "Skipping non-EUR currency line item: #{vli.inspect}"
11
+ next
12
+ end
13
+ ali = AmexLineItem.new vli.posting_date, vli.value, vli.description
14
+ CSV { |out| out << [ali.date, ali.amount, ali.description] }
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ module Volksbanker
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,62 @@
1
+ # Volksbank format line by line:
2
+ #
3
+ # Lines 1-13: header
4
+ # Subsequent non-blank lines: semi-colon separated values
5
+ # posting date
6
+ # value date
7
+ # payer/payee
8
+ # recipient/payer
9
+ # account no.
10
+ # sortcode
11
+ # description
12
+ # currency
13
+ # amount
14
+ # credit (H) /debit (S)
15
+ # Blank line
16
+ # Footer (opening and closing balances)
17
+
18
+ require 'volksbanker/volksbank_line_item'
19
+ require 'volksbanker/amex_line_item'
20
+
21
+ module Volksbanker
22
+
23
+ class VolksbankFileReader
24
+ def initialize(file)
25
+ @file = file
26
+ end
27
+
28
+ # Yields each transaction line item to the block.
29
+ # I.e. skips the header and footer information.
30
+ def each_line_item(&block)
31
+ data = File.open(@file,'r:iso-8859-1:utf-8') { |f| f.read }
32
+ data = clean_line_breaks data
33
+
34
+ line_number = 0
35
+ data.each_line do |line|
36
+ line_number += 1 # 1-based line numbering
37
+ next if line_number <= 13 # skip header
38
+ line.chomp!
39
+ break if line.empty? # skip footer
40
+
41
+ yield VolksbankLineItem.new_from_csv line
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def clean_line_breaks(str)
48
+ # Format uses \r\n for line breaks between inter-line breaks and \n for intra-line breaks.
49
+ # There must be a neat Ruby way to do this...
50
+ remove_inter_line_breaks remove_intra_line_breaks(str)
51
+ end
52
+
53
+ def remove_intra_line_breaks(str)
54
+ str.gsub /([^\r])\n/, '\1 '
55
+ end
56
+
57
+ def remove_inter_line_breaks(str)
58
+ str.gsub "\r\n", "\n"
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,46 @@
1
+ require 'csv'
2
+
3
+ class VolksbankLineItem
4
+ DATE_FORMAT = '%d.%m.%Y'
5
+
6
+ attr_reader :posting_date, :value_date, :payer_or_payee, :recipient_or_payer,
7
+ :account_number, :sort_code, :description, :currency,
8
+ :value
9
+
10
+ def initialize(posting_date, value_date, payer_or_payee, recipient_or_payer,
11
+ account_number, sort_code, description, currency,
12
+ amount, credit_or_debit)
13
+ @posting_date = parse_date posting_date
14
+ @value_date = parse_date value_date
15
+ @payer_or_payee = payer_or_payee
16
+ @recipient_or_payer = recipient_or_payer
17
+ @account_number = account_number
18
+ @sort_code = sort_code
19
+ @description = description
20
+ @currency = currency
21
+ amt = parse_number amount
22
+ @value = credit?(credit_or_debit) ? amt : (amt * -1)
23
+ end
24
+
25
+ def self.new_from_csv(line)
26
+ CSV.parse(line, col_sep: ';') { |row| return new(*row) }
27
+ end
28
+
29
+ private
30
+
31
+ def parse_date(str)
32
+ Date.strptime str, DATE_FORMAT
33
+ end
34
+
35
+ def parse_number(str)
36
+ str. # There must be a better way to do this!
37
+ gsub('.', ''). # no thousand-separator
38
+ gsub(',', '.'). # use decimal point instead of comma for decimal separator
39
+ to_f
40
+ end
41
+
42
+ def credit?(str)
43
+ str == 'H'
44
+ end
45
+ end
46
+
@@ -0,0 +1,6 @@
1
+ require 'volksbanker/version'
2
+ require 'volksbanker/cli'
3
+ require 'volksbanker/volksbank_file_reader'
4
+ require 'volksbanker/volksbank_line_item'
5
+ require 'volksbanker/amex_line_item'
6
+
data/test/cli_test.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'minitest/autorun'
2
+ require 'test_helper'
3
+ require 'volksbanker/cli'
4
+
5
+ class CliTest < MiniTest::Unit::TestCase
6
+
7
+ def test_happy_path
8
+ expected_stdout = read_fixture 'result.csv'
9
+ expected_stderr = ''
10
+
11
+ assert_output expected_stdout, expected_stderr do
12
+ Volksbanker::Cli.run fixture('transactions.csv')
13
+ end
14
+ end
15
+
16
+ def test_skips_non_euro_line_items
17
+ out, err = capture_io do
18
+ Volksbanker::Cli.run fixture('transactions-with-non-euro.csv')
19
+ end
20
+
21
+ refute_match %r{30/07/2012}m, out
22
+ assert_match /Skipping/, err
23
+ end
24
+
25
+ end
@@ -0,0 +1,7 @@
1
+ 08/08/2012,-7.5,Bankcard-Gebühr FOLGE-NR. 0 VERFALL 12.15 PREIS BEZAHLT BIS 12.2012
2
+ 08/08/2012,170.0,Vergütung INVOICE 7004
3
+ 07/08/2012,170.0,"Vergütung INVOICE 7003 Acme GmbH, JULY 2012"
4
+ 03/08/2012,2023.0,Vergütung INVOICE 7002
5
+ 31/07/2012,68.0,Vergütung RGNR. 2271
6
+ 30/07/2012,136.0,Vergütung INVOICE 7002
7
+ 17/07/2012,170.0,Vergütung INVOICE 2264
@@ -0,0 +1,32 @@
1
+ "Volksbank Rhein-Wehra eG"
2
+
3
+ "Umsatzanzeige"
4
+
5
+ "BLZ:";"68490000";;"Datum:";"13.08.2012"
6
+ "Konto:";"12345678";;"Uhrzeit:";"11:54:07"
7
+ "Abfrage von:";"Joe Bloggs";;"Kontoinhaber:";"Foo GmbH"
8
+
9
+ "Zeitraum:";"4 Wochen";"von:";;"bis:";
10
+ "Betrag in EUR:";;"von:";" ";"bis:";" "
11
+ "Sortiert nach:";"Buchungstag";"absteigend"
12
+
13
+ "Buchungstag";"Valuta";"Auftraggeber/Zahlungsempf�nger";"Empf�nger/Zahlungspflichtiger";"Konto-Nr.";"BLZ";"Vorgang/Verwendungszweck";"W�hrung";"Umsatz";" "
14
+ "08.08.2012";"08.08.2012";;"PREIS VR-BANKCARD";"1234500000";"12340000";"Bankcard-Geb�hr
15
+ FOLGE-NR. 0 VERFALL 12.15
16
+ PREIS BEZAHLT BIS 12.2012";"EUR";"7,50";"S"
17
+ "08.08.2012";"08.08.2012";"Foo GmbH";"Jane Doe";"1234567890";"12345678";"Verg�tung
18
+ INVOICE 7004";"EUR";"170,00";"H"
19
+ "07.08.2012";"07.08.2012";"BarApp";"Sarah Smith";"123456789";"12345678";"Verg�tung
20
+ INVOICE 7003
21
+ Acme GmbH, JULY 2012";"EUR";"170,00";"H"
22
+ "03.08.2012";"03.08.2012";"Foo GmbH";"Some Firm GmbH";"1234567";"12345678";"Verg�tung
23
+ INVOICE 7002";"EUR";"2.023,00";"H"
24
+ "31.07.2012";"31.07.2012";"Foo GmbH";"James Brown";"1234567890";"12345678";"Verg�tung
25
+ RGNR. 2271";"EUR";"68,00";"H"
26
+ "30.07.2012";"30.07.2012";"Foo GmbH";"Example.com";"123456789";"12345678";"Verg�tung
27
+ INVOICE 7002";"GBP";"136,00";"H"
28
+ "17.07.2012";"17.07.2012";"Foo GmbH";"Blah Inc GmbH";"1234567890";"12345678";"Verg�tung
29
+ INVOICE 2264";"EUR";"170,00";"H"
30
+
31
+ "17.07.2012";;;;;;"EUR";"Anfangssaldo";"0,00";"H"
32
+ "08.08.2012";;;;;;"EUR";"Endsaldo";"2.729,50";"H"
@@ -0,0 +1,32 @@
1
+ "Volksbank Rhein-Wehra eG"
2
+
3
+ "Umsatzanzeige"
4
+
5
+ "BLZ:";"68490000";;"Datum:";"13.08.2012"
6
+ "Konto:";"12345678";;"Uhrzeit:";"11:54:07"
7
+ "Abfrage von:";"Joe Bloggs";;"Kontoinhaber:";"Foo GmbH"
8
+
9
+ "Zeitraum:";"4 Wochen";"von:";;"bis:";
10
+ "Betrag in EUR:";;"von:";" ";"bis:";" "
11
+ "Sortiert nach:";"Buchungstag";"absteigend"
12
+
13
+ "Buchungstag";"Valuta";"Auftraggeber/Zahlungsempf�nger";"Empf�nger/Zahlungspflichtiger";"Konto-Nr.";"BLZ";"Vorgang/Verwendungszweck";"W�hrung";"Umsatz";" "
14
+ "08.08.2012";"08.08.2012";;"PREIS VR-BANKCARD";"1234500000";"12340000";"Bankcard-Geb�hr
15
+ FOLGE-NR. 0 VERFALL 12.15
16
+ PREIS BEZAHLT BIS 12.2012";"EUR";"7,50";"S"
17
+ "08.08.2012";"08.08.2012";"Foo GmbH";"Jane Doe";"1234567890";"12345678";"Verg�tung
18
+ INVOICE 7004";"EUR";"170,00";"H"
19
+ "07.08.2012";"07.08.2012";"BarApp";"Sarah Smith";"123456789";"12345678";"Verg�tung
20
+ INVOICE 7003
21
+ Acme GmbH, JULY 2012";"EUR";"170,00";"H"
22
+ "03.08.2012";"03.08.2012";"Foo GmbH";"Some Firm GmbH";"1234567";"12345678";"Verg�tung
23
+ INVOICE 7002";"EUR";"2.023,00";"H"
24
+ "31.07.2012";"31.07.2012";"Foo GmbH";"James Brown";"1234567890";"12345678";"Verg�tung
25
+ RGNR. 2271";"EUR";"68,00";"H"
26
+ "30.07.2012";"30.07.2012";"Foo GmbH";"Example.com";"123456789";"12345678";"Verg�tung
27
+ INVOICE 7002";"EUR";"136,00";"H"
28
+ "17.07.2012";"17.07.2012";"Foo GmbH";"Blah Inc GmbH";"1234567890";"12345678";"Verg�tung
29
+ INVOICE 2264";"EUR";"170,00";"H"
30
+
31
+ "17.07.2012";;;;;;"EUR";"Anfangssaldo";"0,00";"H"
32
+ "08.08.2012";;;;;;"EUR";"Endsaldo";"2.729,50";"H"
@@ -0,0 +1,13 @@
1
+ class MiniTest::Unit::TestCase
2
+
3
+ # Returns full path to fixture file.
4
+ def fixture(filename)
5
+ File.expand_path "../fixtures/#{filename}", __FILE__
6
+ end
7
+
8
+ # Returns contents of fixture file.
9
+ def read_fixture(filename)
10
+ File.open(fixture filename) { |f| f.read }
11
+ end
12
+
13
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "volksbanker/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "volksbanker"
7
+ s.version = Volksbanker::VERSION
8
+ s.authors = ["Andy Stewart"]
9
+ s.email = ["boss@airbladesoftware.com"]
10
+ s.homepage = ""
11
+ s.summary = "Prepares Volksbank's electronic statements for upload to Freeagent."
12
+ s.description = s.summary
13
+
14
+ s.rubyforge_project = "volksbanker"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'rake', '~> 0.9.2'
22
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: volksbanker
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Andy Stewart
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &2159222460 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.2
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2159222460
25
+ description: Prepares Volksbank's electronic statements for upload to Freeagent.
26
+ email:
27
+ - boss@airbladesoftware.com
28
+ executables:
29
+ - vb
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - README.md
36
+ - Rakefile
37
+ - bin/vb
38
+ - lib/volksbanker.rb
39
+ - lib/volksbanker/amex_line_item.rb
40
+ - lib/volksbanker/cli.rb
41
+ - lib/volksbanker/version.rb
42
+ - lib/volksbanker/volksbank_file_reader.rb
43
+ - lib/volksbanker/volksbank_line_item.rb
44
+ - test/cli_test.rb
45
+ - test/fixtures/result.csv
46
+ - test/fixtures/transactions-with-non-euro.csv
47
+ - test/fixtures/transactions.csv
48
+ - test/test_helper.rb
49
+ - volksbanker.gemspec
50
+ homepage: ''
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ segments:
63
+ - 0
64
+ hash: 3400310575893115125
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ segments:
72
+ - 0
73
+ hash: 3400310575893115125
74
+ requirements: []
75
+ rubyforge_project: volksbanker
76
+ rubygems_version: 1.8.11
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Prepares Volksbank's electronic statements for upload to Freeagent.
80
+ test_files:
81
+ - test/cli_test.rb
82
+ - test/fixtures/result.csv
83
+ - test/fixtures/transactions-with-non-euro.csv
84
+ - test/fixtures/transactions.csv
85
+ - test/test_helper.rb