From b45dc6d408030a21809aebde10e8f7982e6a0a43 Mon Sep 17 00:00:00 2001 From: Sander Onland Date: Mon, 20 Jan 2014 19:33:13 +0100 Subject: [PATCH 1/2] added account and balance classes --- lib/mt940.rb | 1 + lib/mt940/account.rb | 20 ++++++++++++++++++++ lib/mt940/base.rb | 24 +++++++++++++++++++++--- lib/mt940/parser.rb | 3 ++- test/mt940_base_test.rb | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 lib/mt940/account.rb diff --git a/lib/mt940.rb b/lib/mt940.rb index 8171cf7..4c44eb1 100644 --- a/lib/mt940.rb +++ b/lib/mt940.rb @@ -5,6 +5,7 @@ require 'mt940/bic_codes' require 'mt940/parser' require 'mt940/base' +require 'mt940/account' require 'mt940/transaction' require 'mt940/banks/ing' require 'mt940/banks/rabobank' diff --git a/lib/mt940/account.rb b/lib/mt940/account.rb new file mode 100644 index 0000000..b4a9003 --- /dev/null +++ b/lib/mt940/account.rb @@ -0,0 +1,20 @@ +module MT940 + + class Account + + attr_accessor :number, :currency, :opening_balance, :closing_balance + + def initialize + @opening_balance = MT940::Balance.new + @closing_balance = MT940::Balance.new + end + end + + class Balance + + attr_accessor :date, :amount + + end + + +end \ No newline at end of file diff --git a/lib/mt940/base.rb b/lib/mt940/base.rb index 03f311f..157d7ba 100644 --- a/lib/mt940/base.rb +++ b/lib/mt940/base.rb @@ -7,11 +7,13 @@ module MT940 class Base - attr_accessor :bank, :transactions + attr_accessor :bank, :transactions, :account def initialize(file) @transactions, @lines = [], [] @bank = self.class.to_s.split('::').last + @account = MT940::Account.new + file.readlines.each do |line| begin_of_line?(line) ? @lines << line : @lines[-1] += line end @@ -32,7 +34,7 @@ def parse when '86' parse_tag_86 if @transaction when '62F' - @transaction = nil #Ignore 'eindsaldo' + parse_tag_62F end end end @@ -47,12 +49,27 @@ def begin_of_line?(line) def parse_tag_25 @line.gsub!('.','') @bank_account = $1.gsub(/^0/,'') if @line.match(/^:\d{2}:[^\d]*(\d*)/) + @account.number = @bank_account end + # opening balance def parse_tag_60F - @currency = @line[12..14] + debet_credit = @line[5].eql?("D") ? -1 : 1 + @account.opening_balance.date = Date.strptime(@line[6..11], "%y%m%d") + @account.opening_balance.amount = debet_credit * @line[15..-1].gsub(',', '.').to_f + @account.currency = @line[12..14] + @currency = @account.currency end + # closing balance + def parse_tag_62F + debet_credit = @line[5].eql?("D") ? -1 : 1 + @account.closing_balance.date = Date.strptime(@line[6..11], "%y%m%d") + @account.closing_balance.amount = debet_credit * @line[15..-1].gsub(',', '.').to_f + @account.currency = @line[12..14] + @currency = @account.currency + end + def parse_tag_61(pattern = nil) pattern = pattern || /^:61:(\d{6})(C|D)(\d+),(\d{0,2})/ match = @line.match(pattern) @@ -72,6 +89,7 @@ def parse_tag_86 end end + def hashify_description(description) hash = {} description.gsub!(/[^A-Z]\/[^A-Z]/,' ') #Remove single forward slashes '/', which are not part of a swift code diff --git a/lib/mt940/parser.rb b/lib/mt940/parser.rb index 3bd5582..e13ef7b 100644 --- a/lib/mt940/parser.rb +++ b/lib/mt940/parser.rb @@ -5,7 +5,7 @@ class UnknownBank < Exception; end class Parser - attr_accessor :transactions + attr_accessor :transactions, :account def initialize(file) file = File.open(file) if file.is_a?(String) @@ -25,6 +25,7 @@ def process(file) instance = bank_class.new(file) instance.parse @transactions = instance.transactions + @account = instance.account rescue NoMethodError => exception if exception.message == "undefined method `new' for nil:NilClass" raise UnknownBank.new('Could not determine bank!') diff --git a/test/mt940_base_test.rb b/test/mt940_base_test.rb index a85685c..c5621c4 100644 --- a/test/mt940_base_test.rb +++ b/test/mt940_base_test.rb @@ -40,5 +40,40 @@ class TestMt940Base < Test::Unit::TestCase end end end + + + context 'MT940::Account' do + + setup do + # Fixture contains a mixture of transactions with and without iban numbers + file_name = File.dirname(__FILE__) + '/fixtures/ing_sepa.txt' + @parser = MT940::Parser.new(file_name) + @transactions = @parser.transactions + end + + should 'have the correct accountnumber' do + assert_equal "654321789", @parser.account.number + end + + should 'have the correct currency' do + assert_equal "EUR", @parser.account.currency + end + + should 'have the correct opening balance' do + assert_equal "2012-08-10", @parser.account.opening_balance.date.to_s + assert_equal 68.20 , @parser.account.opening_balance.amount + end + + should 'have the correct closing balance' do + assert_equal "2012-08-11", @parser.account.closing_balance.date.to_s + assert_equal 1005.83 , @parser.account.closing_balance.amount + end + + # the difference between the opening and closing balance should equal the net change of transactions + should 'calculate the correct difference between the opening and closing balance' do + assert_equal @transactions.map(&:amount).reduce(:+), @parser.account.closing_balance.amount - @parser.account.opening_balance.amount + end + + end end From b2b15ca584788f5f65fbcc007d8349d6c851ac4d Mon Sep 17 00:00:00 2001 From: Sander Onland Date: Wed, 22 Jan 2014 11:50:37 +0100 Subject: [PATCH 2/2] things went terribly wrong at ING --- lib/mt940/banks/ing.rb | 20 +++++++++++++++----- lib/mt940/banks/rabobank.rb | 1 + lib/mt940/base.rb | 10 ++++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/mt940/banks/ing.rb b/lib/mt940/banks/ing.rb index cb14198..fa21fee 100644 --- a/lib/mt940/banks/ing.rb +++ b/lib/mt940/banks/ing.rb @@ -3,20 +3,30 @@ class MT940::Ing < MT940::Base private def parse_line_before_sepa - pattern = Regexp.new "(#{MT940::BBAN_PATTERN})(.+)" + pattern = Regexp.new "(#{MT940::BBAN_PATTERN}|#{MT940::IBAN_PATTERN}|\s)(.+)" if @line.match(pattern) @description = $2.strip - @contra_account = $1[/[^0+]\d*/] + @contra_account = $1 #[/[^0+]\d*/] end end def parse_line_after_sepa - if @line.match(MT940::SEPA_PATTERN) - @contra_account = $2 - @description = $4.strip + pattern = Regexp.new "(#{MT940::SEPA_PATTERN})(.+)" + if @line.match(pattern) + @description = $2.strip + @contra_account = $1 end end + def parse_tag_86 + if @line.match(/^:86:(.*)$/) + @line = $1.strip + sepa? ? parse_line_after_sepa : parse_line_before_sepa + @transaction.contra_account = @contra_account + @transaction.description = @description + end + end + def sepa? @line.match(MT940::SEPA_PATTERN) end diff --git a/lib/mt940/banks/rabobank.rb b/lib/mt940/banks/rabobank.rb index f3afa15..82bf833 100644 --- a/lib/mt940/banks/rabobank.rb +++ b/lib/mt940/banks/rabobank.rb @@ -10,6 +10,7 @@ def parse_tag_25 else @bank_account = $1.gsub(/^0/,'') if @line.match(/^:\d{2}:[^\d]*(\d*)/) end + @account.number = @bank_account end def parse_tag_61 diff --git a/lib/mt940/base.rb b/lib/mt940/base.rb index 157d7ba..0e020c5 100644 --- a/lib/mt940/base.rb +++ b/lib/mt940/base.rb @@ -101,10 +101,12 @@ def hashify_description(description) def create_transaction(match) type = match[2] == 'D' ? -1 : 1 - MT940::Transaction.new(:bank_account => @bank_account, - :amount => type * (match[3] + '.' + match[4]).to_f, - :bank => @bank, - :currency => @currency) + MT940::Transaction.new( + :bank_account => @bank_account, + :amount => type * (match[3] + '.' + match[4]).to_f, + :bank => @bank, + :currency => @currency + ) end def parse_date(string)