diff --git a/.gitignore b/.gitignore index 2288186..909f0c8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,10 @@ doc # jeweler generated pkg -# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: +# never ever commit the Gemfile.lock +Gemfile.lock + +# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: # # * Create a file at ~/.gitignore # * Include files you want ignored diff --git a/.rvmrc b/.rvmrc deleted file mode 100644 index 2a08691..0000000 --- a/.rvmrc +++ /dev/null @@ -1 +0,0 @@ -rvm use --create 1.8.7@mt940_parser diff --git a/Gemfile b/Gemfile index 844ea76..12d1f4d 100644 --- a/Gemfile +++ b/Gemfile @@ -2,12 +2,11 @@ source :rubygems group :development do gem 'awesome_print' - gem "rspec" - gem "bundler", "~> 1.0.0" - gem "jeweler", "~> 1.5.2" - gem "ruby-debug", :platforms => :ruby_18 - gem "ruby-debug19", :platforms => :ruby_19, :require => 'ruby_debug' - gem "simplecov", :platforms => :ruby_19 - gem "rcov", :platforms => :ruby_18 - gem "rdoc" + gem 'minitest' + gem 'rspec' + gem 'bundler', '~> 1.11.2' + gem 'jeweler', '~> 2.0.1' + gem 'ruby-debug19', platforms: :ruby_19, require: 'ruby_debug' + gem 'simplecov', platforms: :ruby_19 + gem 'rdoc' end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 16b7724..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,64 +0,0 @@ -GEM - remote: http://rubygems.org/ - specs: - archive-tar-minitar (0.5.2) - awesome_print (1.0.2) - columnize (0.3.6) - diff-lcs (1.1.3) - git (1.2.5) - jeweler (1.5.2) - bundler (~> 1.0.0) - git (>= 1.2.5) - rake - json (1.7.0) - linecache (0.46) - rbx-require-relative (> 0.0.4) - linecache19 (0.5.12) - ruby_core_source (>= 0.1.4) - multi_json (1.3.4) - rake (0.9.2.2) - rbx-require-relative (0.0.9) - rcov (1.0.0) - rdoc (3.12) - json (~> 1.4) - rspec (2.3.0) - rspec-core (~> 2.3.0) - rspec-expectations (~> 2.3.0) - rspec-mocks (~> 2.3.0) - rspec-core (2.3.1) - rspec-expectations (2.3.0) - diff-lcs (~> 1.1.2) - rspec-mocks (2.3.0) - ruby-debug (0.10.4) - columnize (>= 0.1) - ruby-debug-base (~> 0.10.4.0) - ruby-debug-base (0.10.4) - linecache (>= 0.3) - ruby-debug-base19 (0.11.25) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby_core_source (>= 0.1.4) - ruby-debug19 (0.11.6) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby-debug-base19 (>= 0.11.19) - ruby_core_source (0.1.5) - archive-tar-minitar (>= 0.5.2) - simplecov (0.6.2) - multi_json (~> 1.3) - simplecov-html (~> 0.5.3) - simplecov-html (0.5.3) - -PLATFORMS - ruby - -DEPENDENCIES - awesome_print - bundler (~> 1.0.0) - jeweler (~> 1.5.2) - rcov - rdoc - rspec - ruby-debug - ruby-debug19 - simplecov diff --git a/Rakefile b/Rakefile index ca57ac3..a741d7a 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + $stderr.puts 'Run `bundle install` to install missing gems' exit e.status_code end require 'rake' @@ -13,17 +13,17 @@ require 'rake' begin require 'jeweler' Jeweler::Tasks.new do |gem| - gem.name = "mt940_parser" - gem.summary = %Q{MT940 parses account statements in the SWIFT MT940 format.} - gem.license = "MIT" - gem.email = "developers@betterplace.org" - gem.homepage = "http://github.com/betterplace/mt940_parser" - gem.authors = ["Thies C. Arntzen", "Phillip Oertel"] + gem.name = 'mt940_parser' + gem.summary = %(MT940 parses account statements in the SWIFT MT940 format.) + gem.license = 'MIT' + gem.email = 'developers@betterplace.org' + gem.homepage = 'http://github.com/betterplace/mt940_parser' + gem.authors = ['Thies C. Arntzen', 'Phillip Oertel'] # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings end Jeweler::GemcutterTasks.new rescue LoadError - puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" + puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler' end require 'rake/testtask' @@ -38,18 +38,18 @@ RSpec::Core::RakeTask.new(:rspec) do |t| t.rspec_opts = '--color --format documentation' end -desc "Run all specs with rcov" +desc 'Run all specs with rcov' RSpec::Core::RakeTask.new(:rcov) do |t| t.rspec_opts = '--color --format documentation' t.rcov = true t.rcov_opts = '--exclude /gems/,spec' end -task :default => :test +task default: :test require 'rdoc/task' Rake::RDocTask.new do |rdoc| - version = File.exist?('VERSION') ? File.read('VERSION') : "" + version = File.exist?('VERSION') ? File.read('VERSION') : '' rdoc.rdoc_dir = 'rdoc' rdoc.title = "mt940 #{version}" diff --git a/lib/mt940.rb b/lib/mt940.rb index d4325f3..db14e5b 100644 --- a/lib/mt940.rb +++ b/lib/mt940.rb @@ -10,10 +10,11 @@ class Field SHORT_DATE = /(\d{2})(\d{2})/ class << self - def for(line) - if line.match(/^:(\d{2,2})(\w)?:(.*)/m) - number, modifier, content = $1, $2, $3 + if line =~ /^:(\d{2,2})(\w)?:(.*)/m + number = Regexp.last_match(1) + modifier = Regexp.last_match(2) + content = Regexp.last_match(3) klass = { '20' => Job, '21' => Reference, @@ -25,7 +26,7 @@ def for(line) '64' => ValutaBalance, '65' => FutureValutaBalance, '86' => InformationToAccountOwner - }[number] #Probably be using Hash.fetch(number) + }[number] # Probably be using Hash.fetch(number) raise StandardError, "Field #{number} is not implemented" unless klass @@ -48,24 +49,25 @@ def initialize(modifier, content) end private - def parse_amount_in_cents(amount) - # don't use Integer(amount) function, because amount can be "008" - interpreted as octal number ("010" = 8) - BigDecimal.new(amount.gsub(',', '.')) * 100 - end - def parse_date(date) - date.match(DATE) - Date.new("20#{$1}".to_i, $2.to_i, $3.to_i) - end + def parse_amount_in_cents(amount) + # don't use Integer(amount) function, because amount can be "008" - interpreted as octal number ("010" = 8) + BigDecimal.new(amount.tr(',', '.')) * 100 + end - def parse_entry_date(raw_entry_date, value_date) - raw_entry_date.match(SHORT_DATE) - entry_date = Date.new(value_date.year, $1.to_i, $2.to_i) - if (entry_date.year != value_date.year) - raise "Unhandled case: value date and entry date are in different years" - end - entry_date + def parse_date(date) + date.match(DATE) + Date.new("20#{Regexp.last_match(1)}".to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i) + end + + def parse_entry_date(raw_entry_date, value_date) + raw_entry_date.match(SHORT_DATE) + entry_date = Date.new(value_date.year, Regexp.last_match(1).to_i, Regexp.last_match(2).to_i) + if entry_date.year != value_date.year + raise 'Unhandled case: value date and entry date are in different years' end + entry_date + end end # 20 @@ -84,7 +86,7 @@ class Reference < Job # 25 class AccountIdentification attr_reader :account_identifier - MATCHER_REGEX = /(.{1,35})/ #any 35 chars (35x from the docs) + MATCHER_REGEX = /(.{1,35})/ # any 35 chars (35x from the docs) def initialize(modifier, content) @modifier = modifier @@ -97,28 +99,29 @@ def parse_content(content) end # fail over to the old Account class - def method_missing(method, *args, &block) + def method_missing(method, *_args, &_block) @fail_over_implementation ||= Account.new(@modifier, @content) @fail_over_implementation.send(method) end end - class Account < Field - #This is not how field 25 behaves - #The documentation states that the contents of this field is + # This is not how field 25 behaves + # The documentation states that the contents of this field is # # 35x # - #so you can only attribute a account number (usually as a IBAN). + # so you can only attribute a account number (usually as a IBAN). attr_reader :bank_code, :account_number, :account_currency CONTENT = /^(.{8,11})\/(\d{0,23})([A-Z]{3})?$/ def parse_content(content) - warn "MT940::Account should be deprecated" + warn 'MT940::Account should be deprecated' content.match(CONTENT) - @bank_code, @account_number, @account_currency = $1, $2, $3 + @bank_code = Regexp.last_match(1) + @account_number = Regexp.last_match(2) + @account_currency = Regexp.last_match(3) end end @@ -137,7 +140,6 @@ def initialize(modifier, content) def parse_content(content) @number, @sequence = content.split('/') end - end class Statement < Field @@ -148,16 +150,17 @@ class Statement < Field def parse_content(content) warn 'MT940::Statement is deprecated' content.match(CONTENT) - if $1 == '0' + if Regexp.last_match(1) == '0' @number = @sheet = 0 else - @number, @sheet = $2.to_i, $3.to_i + @number = Regexp.last_match(2).to_i + @sheet = Regexp.last_match(3).to_i end end end class AccountBalance < Field - #This needs to be refactored. + # This needs to be refactored. attr_reader :balance_type, :sign, :currency, :amount, :date CONTENT = /^(C|D)(\w{6})(\w{3})(\d{1,12},\d{0,2})$/ @@ -166,31 +169,31 @@ def parse_content(content) content.match(CONTENT) @balance_type = case @modifier - when 'F' - :start - when 'M' - :intermediate + when 'F' + :start + when 'M' + :intermediate end - @sign = case $1 - when 'C' - :credit - when 'D' - :debit + @sign = case Regexp.last_match(1) + when 'C' + :credit + when 'D' + :debit end - raw_date = $2 + raw_date = Regexp.last_match(2) - @currency = $3 + @currency = Regexp.last_match(3) - amount_str = $4.gsub(/,/, '.') + amount_str = Regexp.last_match(4).tr(',', '.') @amount = BigDecimal.new(amount_str) @date = case raw_date - when 'ALT', '0' - nil - when DATE - Date.new("20#{$1}".to_i, $2.to_i, $3.to_i) + when 'ALT', '0' + nil + when DATE + Date.new("20#{Regexp.last_match(1)}".to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i) end end end @@ -204,23 +207,23 @@ class StatementLine < Field def parse_content(content) content.match(CONTENT) - raw_date = $1 - raw_entry_date = $2 - @funds_code = case $3 - when 'C' - :credit - when 'D' - :debit - when 'RC' - :return_credit - when 'RD' - :return_debit + raw_date = Regexp.last_match(1) + raw_entry_date = Regexp.last_match(2) + @funds_code = case Regexp.last_match(3) + when 'C' + :credit + when 'D' + :debit + when 'RC' + :return_credit + when 'RD' + :return_debit end - @amount = parse_amount_in_cents($4) - @swift_code = $5 - @reference = $6 - @transaction_description = $7 + @amount = parse_amount_in_cents(Regexp.last_match(4)) + @swift_code = Regexp.last_match(5) + @reference = Regexp.last_match(6) + @transaction_description = Regexp.last_match(7) @date = parse_date(raw_date) @entry_date = parse_entry_date(raw_entry_date, @date) if raw_entry_date @@ -263,8 +266,8 @@ def parse_content(content) end end - #Failover to StatementLineInformation - def method_missing(method, *args, &block) + # Failover to StatementLineInformation + def method_missing(method, *_args, &_block) @fail_over_implementation ||= StatementLineInformation.new(@modifier, @content) @fail_over_implementation.send(method) end @@ -274,36 +277,35 @@ class StatementLineInformation < Field # This class again is doing too much and appears to be specific to a # particular implementation and does not appear to follow the swift standard. attr_reader :code, :transaction_description, :prima_nota, :details, :bank_code, :account_number, - :account_holder, :text_key_extension, :not_implemented_fields + :account_holder, :text_key_extension, :not_implemented_fields def parse_content(content) warn 'StatementLineInformation should be deprecated' - content.match(/^(\d{3})((.).*)$/) - @code = $1.to_i + content =~ /^(\d{3})((.).*)$/ + @code = Regexp.last_match(1).to_i details = [] account_holder = [] - if seperator = $3 - sub_fields = $2.scan(/#{Regexp.escape(seperator)}(\d{2})([^#{Regexp.escape(seperator)}]*)/) - + if seperator = Regexp.last_match(3) + sub_fields = Regexp.last_match(2).scan(/#{Regexp.escape(seperator)}(\d{2})([^#{Regexp.escape(seperator)}]*)/) sub_fields.each do |(code, content)| case code.to_i - when 0 - @transaction_description = content - when 10 - @prima_nota = content - when 20..29, 60..63 - details << content - when 30 - @bank_code = content - when 31 - @account_number = content - when 32..33 - account_holder << content - when 34 - @text_key_extension = content + when 0 + @transaction_description = content + when 10 + @prima_nota = content + when 20..29, 60..63 + details << content + when 30 + @bank_code = content + when 31 + @account_number = content + when 32..33 + account_holder << content + when 34 + @text_key_extension = content else @not_implemented_fields ||= [] @not_implemented_fields << [code, content] @@ -318,20 +320,19 @@ def parse_content(content) end end - class << self def parse(text) stripped = text.clone.strip - stripped << "\r\n" if stripped[-1,1] == '-' + stripped << "\r\n" if stripped[-1, 1] == '-' raw_sheets = stripped.split(/^-\r\n/).map { |sheet| sheet.gsub(/\r\n(?!:)/, '') } raw_sheets.map { |raw_sheet| parse_sheet(raw_sheet) } end - private + def parse_sheet(sheet) lines = sheet.split(/\r?\n\s*(?=:)/) - fields = lines.reject { |line| line.empty? }.map { |line| Field.for(line) } + fields = lines.reject(&:empty?).map { |line| Field.for(line) } fields end end diff --git a/lib/mt940/customer_statement_message.rb b/lib/mt940/customer_statement_message.rb index f248509..de0169d 100644 --- a/lib/mt940/customer_statement_message.rb +++ b/lib/mt940/customer_statement_message.rb @@ -2,13 +2,11 @@ # MT940.parse command. use it in order to make dealing with # the data easier class MT940 - class CustomerStatementMessage - attr_reader :statement_lines def self.parse_file(file) - self.parse(File.read(file)) + parse(File.read(file)) end def self.parse(data) @@ -22,8 +20,8 @@ def initialize(raw_mt940) @statement_lines = [] @raw.each_with_index do |line, i| next unless line.class == MT940::StatementLine - ensure_is_info_line!(@raw[i+1]) - @statement_lines << StatementLineBundle.new(@raw[i], @raw[i+1]) + ensure_is_info_line!(@raw[i + 1]) + @statement_lines << StatementLineBundle.new(@raw[i], @raw[i + 1]) end end @@ -47,32 +45,29 @@ def ensure_is_info_line!(line) raise StandardError, "Unexpected Structure; expected StatementLineInformation, but was #{line.class}" end end - end class StatementLineBundle - METHOD_MAP = { - :amount => :line, - :funds_code => :line, - :value_date => :line, - :entry_date => :line, - :account_holder => :info, - :details => :info, - :account_number => :info, - :bank_code => :info, - } + amount: :line, + funds_code: :line, + value_date: :line, + entry_date: :line, + account_holder: :info, + details: :info, + account_number: :info, + bank_code: :info + }.freeze def initialize(statement_line, statement_line_info) - @line, @info = statement_line, statement_line_info + @line = statement_line + @info = statement_line_info end def method_missing(method, *args, &block) - super unless METHOD_MAP.has_key?(method) + super unless METHOD_MAP.key?(method) object = instance_variable_get("@#{METHOD_MAP[method.to_sym]}") object.send(method) end - end - end diff --git a/mt940_parser.gemspec b/mt940_parser.gemspec index cd61fab..4d4536b 100644 --- a/mt940_parser.gemspec +++ b/mt940_parser.gemspec @@ -4,126 +4,125 @@ # -*- encoding: utf-8 -*- Gem::Specification.new do |s| - s.name = "mt940_parser" - s.version = "1.1.0" + s.name = 'mt940_parser' + s.version = '1.1.0' - s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= - s.authors = ["Thies C. Arntzen", "Phillip Oertel"] - s.date = "2012-05-31" - s.email = "developers@betterplace.org" + s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version= + s.authors = ['Thies C. Arntzen', 'Phillip Oertel'] + s.date = '2012-05-31' + s.email = 'developers@betterplace.org' s.extra_rdoc_files = [ - "LICENSE", - "README.rdoc" + 'LICENSE', + 'README.rdoc' ] s.files = [ - ".document", - ".rspec", - ".rvmrc", - ".specification", - "Gemfile", - "Gemfile.lock", - "LICENSE", - "README.rdoc", - "Rakefile", - "VERSION.yml", - "docs/0E0Y00DNY.pdf", - "docs/FinTS_4.0_Formals.pdf", - "docs/FinTS_4.0_Messages_Finanzdatenformate.pdf", - "docs/MT940_Deutschland_Structure2002.pdf", - "docs/SEPA_20MT940__Schnittstellenbeschreibung.pdf", - "docs/mt940.pdf", - "docs/swift_mt940_942.pdf", - "docs/uebersicht_der_geschaeftsvorfallcodes_und_buchungs_textschluessel.pdf", - "lib/mt940.rb", - "lib/mt940/customer_statement_message.rb", - "mt940_parser.gemspec", - "spec/customer_statement_message_spec.rb", - "spec/fixtures/currency_in_25.txt", - "spec/fixtures/currency_in_25.yml", - "spec/fixtures/empty_86.txt", - "spec/fixtures/empty_86.yml", - "spec/fixtures/empty_entry_date.txt", - "spec/fixtures/empty_entry_date.yml", - "spec/fixtures/empty_line.txt", - "spec/fixtures/empty_line.yml", - "spec/fixtures/missing_crlf_at_end.txt", - "spec/fixtures/missing_crlf_at_end.yml", - "spec/fixtures/sepa_mt9401.txt", - "spec/fixtures/sepa_mt9401.yml", - "spec/fixtures/sepa_snippet.txt", - "spec/fixtures/sepa_snippet_broken.txt", - "spec/fixtures/with_binary_character.txt", - "spec/fixtures/with_binary_character.yml", - "spec/mt940_spec.rb", - "spec/spec_helper.rb", - "test/fixtures/currency_in_25.txt", - "test/fixtures/currency_in_25.yml", - "test/fixtures/empty_86.txt", - "test/fixtures/empty_86.yml", - "test/fixtures/empty_entry_date.txt", - "test/fixtures/empty_entry_date.yml", - "test/fixtures/empty_line.txt", - "test/fixtures/empty_line.yml", - "test/fixtures/missing_crlf_at_end.txt", - "test/fixtures/missing_crlf_at_end.yml", - "test/fixtures/sepa_mt9401.txt", - "test/fixtures/sepa_mt9401.yml", - "test/fixtures/sepa_snippet.txt", - "test/fixtures/sepa_snippet_broken.txt", - "test/fixtures/with_binary_character.txt", - "test/fixtures/with_binary_character.yml", - "test/helper.rb", - "test/test_customer_statement_message.rb", - "test/test_mt940.rb" + '.document', + '.rspec', + '.rvmrc', + '.specification', + 'Gemfile', + 'Gemfile.lock', + 'LICENSE', + 'README.rdoc', + 'Rakefile', + 'VERSION.yml', + 'docs/0E0Y00DNY.pdf', + 'docs/FinTS_4.0_Formals.pdf', + 'docs/FinTS_4.0_Messages_Finanzdatenformate.pdf', + 'docs/MT940_Deutschland_Structure2002.pdf', + 'docs/SEPA_20MT940__Schnittstellenbeschreibung.pdf', + 'docs/mt940.pdf', + 'docs/swift_mt940_942.pdf', + 'docs/uebersicht_der_geschaeftsvorfallcodes_und_buchungs_textschluessel.pdf', + 'lib/mt940.rb', + 'lib/mt940/customer_statement_message.rb', + 'mt940_parser.gemspec', + 'spec/customer_statement_message_spec.rb', + 'spec/fixtures/currency_in_25.txt', + 'spec/fixtures/currency_in_25.yml', + 'spec/fixtures/empty_86.txt', + 'spec/fixtures/empty_86.yml', + 'spec/fixtures/empty_entry_date.txt', + 'spec/fixtures/empty_entry_date.yml', + 'spec/fixtures/empty_line.txt', + 'spec/fixtures/empty_line.yml', + 'spec/fixtures/missing_crlf_at_end.txt', + 'spec/fixtures/missing_crlf_at_end.yml', + 'spec/fixtures/sepa_mt9401.txt', + 'spec/fixtures/sepa_mt9401.yml', + 'spec/fixtures/sepa_snippet.txt', + 'spec/fixtures/sepa_snippet_broken.txt', + 'spec/fixtures/with_binary_character.txt', + 'spec/fixtures/with_binary_character.yml', + 'spec/mt940_spec.rb', + 'spec/spec_helper.rb', + 'test/fixtures/currency_in_25.txt', + 'test/fixtures/currency_in_25.yml', + 'test/fixtures/empty_86.txt', + 'test/fixtures/empty_86.yml', + 'test/fixtures/empty_entry_date.txt', + 'test/fixtures/empty_entry_date.yml', + 'test/fixtures/empty_line.txt', + 'test/fixtures/empty_line.yml', + 'test/fixtures/missing_crlf_at_end.txt', + 'test/fixtures/missing_crlf_at_end.yml', + 'test/fixtures/sepa_mt9401.txt', + 'test/fixtures/sepa_mt9401.yml', + 'test/fixtures/sepa_snippet.txt', + 'test/fixtures/sepa_snippet_broken.txt', + 'test/fixtures/with_binary_character.txt', + 'test/fixtures/with_binary_character.yml', + 'test/helper.rb', + 'test/test_customer_statement_message.rb', + 'test/test_mt940.rb' ] - s.homepage = "http://github.com/betterplace/mt940_parser" - s.licenses = ["MIT"] - s.require_paths = ["lib"] - s.rubygems_version = "1.8.15" - s.summary = "MT940 parses account statements in the SWIFT MT940 format." + s.homepage = 'http://github.com/betterplace/mt940_parser' + s.licenses = ['MIT'] + s.require_paths = ['lib'] + s.rubygems_version = '1.8.15' + s.summary = 'MT940 parses account statements in the SWIFT MT940 format.' s.test_files = [ - "spec/customer_statement_message_spec.rb", - "spec/mt940_spec.rb", - "spec/spec_helper.rb", - "test/helper.rb", - "test/test_customer_statement_message.rb", - "test/test_mt940.rb" + 'spec/customer_statement_message_spec.rb', + 'spec/mt940_spec.rb', + 'spec/spec_helper.rb', + 'test/helper.rb', + 'test/test_customer_statement_message.rb', + 'test/test_mt940.rb' ] - if s.respond_to? :specification_version then + if s.respond_to? :specification_version s.specification_version = 3 - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, ["~> 1.0.0"]) - s.add_development_dependency(%q, ["~> 1.5.2"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) - s.add_development_dependency(%q, [">= 0"]) + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') + s.add_development_dependency('awesome_print', ['>= 0']) + s.add_development_dependency('rspec', ['>= 0']) + s.add_development_dependency('bundler', ['~> 1.0.0']) + s.add_development_dependency('jeweler', ['~> 1.5.2']) + s.add_development_dependency('ruby-debug', ['>= 0']) + s.add_development_dependency('ruby-debug19', ['>= 0']) + s.add_development_dependency('simplecov', ['>= 0']) + s.add_development_dependency('rcov', ['>= 0']) + s.add_development_dependency('rdoc', ['>= 0']) else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 1.0.0"]) - s.add_dependency(%q, ["~> 1.5.2"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) + s.add_dependency('awesome_print', ['>= 0']) + s.add_dependency('rspec', ['>= 0']) + s.add_dependency('bundler', ['~> 1.0.0']) + s.add_dependency('jeweler', ['~> 1.5.2']) + s.add_dependency('ruby-debug', ['>= 0']) + s.add_dependency('ruby-debug19', ['>= 0']) + s.add_dependency('simplecov', ['>= 0']) + s.add_dependency('rcov', ['>= 0']) + s.add_dependency('rdoc', ['>= 0']) end else - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, ["~> 1.0.0"]) - s.add_dependency(%q, ["~> 1.5.2"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) - s.add_dependency(%q, [">= 0"]) + s.add_dependency('awesome_print', ['>= 0']) + s.add_dependency('rspec', ['>= 0']) + s.add_dependency('bundler', ['~> 1.0.0']) + s.add_dependency('jeweler', ['~> 1.5.2']) + s.add_dependency('ruby-debug', ['>= 0']) + s.add_dependency('ruby-debug19', ['>= 0']) + s.add_dependency('simplecov', ['>= 0']) + s.add_dependency('rcov', ['>= 0']) + s.add_dependency('rdoc', ['>= 0']) end end - diff --git a/spec/customer_statement_message_spec.rb b/spec/customer_statement_message_spec.rb index 809e98c..3fa0692 100644 --- a/spec/customer_statement_message_spec.rb +++ b/spec/customer_statement_message_spec.rb @@ -2,27 +2,26 @@ require 'mt940' require 'mt940/customer_statement_message' -#TODO: Make sure name align closly with the MT940 specifications -#TODO: Add a method to get the currency of the account. +# TODO: Make sure name align closly with the MT940 specifications +# TODO: Add a method to get the currency of the account. describe MT940::CustomerStatementMessage do - - let(:file) { File.dirname(__FILE__) + "/fixtures/sepa_snippet.txt" } + let(:file) { File.dirname(__FILE__) + '/fixtures/sepa_snippet.txt' } let(:messages) { MT940::CustomerStatementMessage.parse_file(file) } let(:message) { messages.first } let(:message_2) { messages.last } it 'has a bank code' do - message.bank_code.should == "50880050" + expect(message.bank_code).to eq('50880050') end it 'has a account number' do - message.account_number.should == "0194787400888" + expect(message.account_number).to eq('0194787400888') end it 'has statement lines' do - message.statement_lines.should respond_to(:each) - message.statement_lines.size.should == 4 + expect(message.statement_lines).to respond_to(:each) + expect(message.statement_lines.size).to eq(4) end it 'handles multi-lines for Information to Account owners fields' do @@ -37,65 +36,65 @@ -" statement = MT940::CustomerStatementMessage.parse(message).first - statement.narrative.should == ['NAME ACCOUNT OWNER:SOME ENTITY', - 'ACCOUNT DESCRIPTION: CURR'] - + expect(statement.narrative).to eq(['NAME ACCOUNT OWNER:SOME ENTITY', + 'ACCOUNT DESCRIPTION: CURR']) end context 'statement lines' do - #TODO: I don't like the use of fixtures here as it is difficult to see - #what is being tested and why the tests have those values. I want to inline - #some of the examples in the fixtures. + # TODO: I don't like the use of fixtures here as it is difficult to see + # what is being tested and why the tests have those values. I want to inline + # some of the examples in the fixtures. - #TODO: These tests should maybe go into a separate file and test through + # TODO: These tests should maybe go into a separate file and test through # the StatementLineBundle class let(:line) { message.statement_lines.first } it 'have credited amounts' do - #TODO: This should maybe return a Money object based on the currency in the - #statement. - line.amount.should == 5099005 - #TODO: funds_code doesn't seam like a good name for this, will need to check - #the docs to find a more appropriate name. Suggestions: mark, direction. - line.funds_code.should == :credit + # TODO: This should maybe return a Money object based on the currency in the + # statement. + expect(line.amount).to eq(5_099_005) + # TODO: funds_code doesn't seam like a good name for this, will need to check + # the docs to find a more appropriate name. Suggestions: mark, direction. + expect(line.funds_code).to eq(:credit) end it 'have debited amounts' do line = message_2.statement_lines.first - #TODO: Same as above. - line.amount.should == 8 - line.funds_code.should == :debit + # TODO: Same as above. + expect(line.amount).to eq(8) + expect(line.funds_code).to eq(:debit) end it 'have a account holder' do - #TODO: There should be better string formatting here - line.account_holder.should == "KARL\n KAUFMANN" + # TODO: There should be better string formatting here + expect(line.account_holder).to eq("KARL\n KAUFMANN") end it 'has statement lines that have a bank code' do - #TODO: check this method has a appropriate name. - line.bank_code.should == "DRESDEFF508" + # TODO: check this method has a appropriate name. + expect(line.bank_code).to eq('DRESDEFF508') end it 'has statement lines that a have account number' do - #TODO: check this method has a appropriate name. - line.account_number.should == "DE14508800500194785000" + # TODO: check this method has a appropriate name. + expect(line.account_number).to eq('DE14508800500194785000') end it 'has details' do - #TODO: Maybe change #details to #narrative - line.details.should == + # TODO: Maybe change #details to #narrative + expect(line.details).to eq( "EREF+EndToEndId TFNR 22 004\n 00001\nSVWZ+Verw CTSc-01 BC-PPP TF\nNr 22 004" + ) end it 'has an entry date' do - #TODO: check this method has a appropriate name. - line.entry_date.should == Date.parse("2007-09-04") + # TODO: check this method has a appropriate name. + expect(line.entry_date).to eq(Date.parse('2007-09-04')) end it 'has a value date' do - #TODO: check this method has a appropriate name. - line.value_date.should == Date.parse("2007-09-07") + # TODO: check this method has a appropriate name. + expect(line.value_date).to eq(Date.parse('2007-09-07')) end it 'raises a no method error when asking for unknown info' do @@ -105,15 +104,14 @@ it 'parses a message file into individual statements' do messages = MT940::CustomerStatementMessage.parse_file(file) - messages.size.should == 2 - messages[0].account_number.should == "0194787400888" - messages[1].account_number.should == "0194791600888" + expect(messages.size).to eq(2) + expect(messages[0].account_number).to eq('0194787400888') + expect(messages[1].account_number).to eq('0194791600888') end it 'fails when it parses a file with a broken structure' do - file = File.dirname(__FILE__) + "/fixtures/sepa_snippet_broken.txt" - #TODO: I think raising a more specific error is better. + file = File.dirname(__FILE__) + '/fixtures/sepa_snippet_broken.txt' + # TODO: I think raising a more specific error is better. expect { MT940::CustomerStatementMessage.parse_file(file) }.to raise_error StandardError end - end diff --git a/spec/mt940_spec.rb b/spec/mt940_spec.rb index 1f5e9a0..9be41d3 100644 --- a/spec/mt940_spec.rb +++ b/spec/mt940_spec.rb @@ -4,14 +4,14 @@ describe MT940::AccountIdentification do context 'account identifier' do it 'gives back the account identifier string' do - acc_ident = MT940::AccountIdentification.new('some unused modifer','12345690') - acc_ident.account_identifier.should == '12345690' + acc_ident = MT940::AccountIdentification.new('some unused modifer', '12345690') + expect(acc_ident.account_identifier).to eq('12345690') end it 'only gets the first 35 characters' do content = '1' * 40 acc_ident = MT940::AccountIdentification.new('some unused modifer', content) - acc_ident.account_identifier.length.should == 35 + expect(acc_ident.account_identifier.length).to eq(35) end end end @@ -23,8 +23,8 @@ info = MT940::InformationToAccountOwner.new('some unsed modifier', content) - info.narrative.should == ['NAME ACCOUNT OWNER: FEANDO LIMITED', - 'ACCOUNT DESCRIPTION: CURR'] + expect(info.narrative).to eq(['NAME ACCOUNT OWNER: FEANDO LIMITED', + 'ACCOUNT DESCRIPTION: CURR']) end end @@ -34,61 +34,57 @@ subject { MT940::StatementNumber.new('some unused modifier', content) } it 'gives back the number of the statement as a string' do - subject.number.should == '01704' + expect(subject.number).to eq('01704') end it 'gives back the sequence number of the statement' do - subject.sequence.should == '01234' + expect(subject.sequence).to eq('01234') end it 'gives back nil if the sequence number is not included' do statement_number = MT940::StatementNumber.new('some unused modifier', '01704') - statement_number.sequence.should be_nil + expect(statement_number.sequence).to be_nil end - end - require 'ruby-debug' describe MT940::AccountBalance do - let(:account_balance) { MT940::AccountBalance.new('some modifier', 'D120417USD13042,03') } context 'the sign' do it 'is :credit when the first char of the content is "C"' do account_balance = MT940::AccountBalance.new('some modifier', 'C120417USD0,00') - account_balance.sign.should == :credit + expect(account_balance.sign).to eq(:credit) end it 'is :debit when the first char of the content is "D"' do account_balance = MT940::AccountBalance.new('some modifier', 'D120417USD0,00') - account_balance.sign.should == :debit + expect(account_balance.sign).to eq(:debit) end end context 'the balance type' do it 'is :start when the modifier is "F"' do account_balance = MT940::AccountBalance.new('F', 'C120417USD0,00') - account_balance.sign.should == :credit + expect(account_balance.sign).to eq(:credit) end it 'is :intermediate when the modifier is "M"' do account_balance = MT940::AccountBalance.new('M', 'D120417USD0,00') - account_balance.sign.should == :debit + expect(account_balance.sign).to eq(:debit) end end it 'parses the date of the balance from the 6 digits after the sign' do - account_balance.date.should == Date.parse('2012-04-17') + expect(account_balance.date).to eq(Date.parse('2012-04-17')) end it 'parses the currency of the balance' do - account_balance.currency.should == 'USD' + expect(account_balance.currency).to eq('USD') end it 'parses the balance amount into a big decimal' do - account_balance.amount.should be_a BigDecimal - account_balance.amount.should == BigDecimal.new('13042.03') + expect(account_balance.amount).to be_a BigDecimal + expect(account_balance.amount).to eq(BigDecimal.new('13042.03')) end - end end diff --git a/test/helper.rb b/test/helper.rb index d9048a3..93070c1 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,7 +1,8 @@ require 'rubygems' -require 'test/unit' +require 'minitest/autorun' $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) $LOAD_PATH.unshift(File.dirname(__FILE__)) + require 'mt940' require 'mt940/customer_statement_message' diff --git a/test/test_customer_statement_message.rb b/test/test_customer_statement_message.rb index 4ae07ce..f4d6c0c 100644 --- a/test/test_customer_statement_message.rb +++ b/test/test_customer_statement_message.rb @@ -1,89 +1,87 @@ require 'helper' require 'yaml' -#YAML::ENGINE.yamler = 'psych' - +# YAML::ENGINE.yamler = 'psych' # $DEBUG = true -class TestCustomerStatementMessage < Test::Unit::TestCase - +class TestCustomerStatementMessage < Minitest::Test def setup - file = File.dirname(__FILE__) + "/fixtures/sepa_snippet.txt" + file = File.dirname(__FILE__) + '/fixtures/sepa_snippet.txt' messages = MT940::CustomerStatementMessage.parse_file(file) @message = messages.first @message_2 = messages.last end - + def test_it_should_know_the_bank_code - assert_equal "50880050", @message.bank_code + assert_equal '50880050', @message.bank_code end - + def test_it_should_know_the_account_number - assert_equal "0194787400888", @message.account_number + assert_equal '0194787400888', @message.account_number end - + def test_it_should_have_statement_lines assert @message.statement_lines.respond_to?(:each) assert_equal 4, @message.statement_lines.size end - + def test_statement_lines_should_have_amount_info_credit line = @message.statement_lines.first - assert_equal 5099005, line.amount + assert_equal 5_099_005, line.amount assert_equal :credit, line.funds_code end - + def test_statement_lines_should_have_amount_info_debit line = @message_2.statement_lines.first assert_equal 8, line.amount assert_equal :debit, line.funds_code end - + def test_statement_lines_should_have_account_holder line = @message.statement_lines.first assert_equal "KARL\n KAUFMANN", line.account_holder end - + def test_statement_lines_info_should_have_bank_code line = @message.statement_lines.first - assert_equal "DRESDEFF508", line.bank_code + assert_equal 'DRESDEFF508', line.bank_code end - + def test_statement_lines_info_should_have_account_number line = @message.statement_lines.first - assert_equal "DE14508800500194785000", line.account_number + assert_equal 'DE14508800500194785000', line.account_number end - + def test_statement_lines_should_have_details line = @message.statement_lines.first assert_equal "EREF+EndToEndId TFNR 22 004\n 00001\nSVWZ+Verw CTSc-01 BC-PPP TF\nNr 22 004", line.details end - + def test_statement_lines_should_have_an_entry_date line = @message.statement_lines.first - assert_equal Date.parse("2007-09-04"), line.entry_date + assert_equal Date.parse('2007-09-04'), line.entry_date end - + def test_statement_lines_should_have_a_value_date line = @message.statement_lines.first - assert_equal Date.parse("2007-09-07"), line.value_date + assert_equal Date.parse('2007-09-07'), line.value_date end - + def test_parsing_the_file_should_return_two_message_objects - file = File.dirname(__FILE__) + "/fixtures/sepa_snippet.txt" + file = File.dirname(__FILE__) + '/fixtures/sepa_snippet.txt' messages = MT940::CustomerStatementMessage.parse_file(file) assert_equal 2, messages.size - assert_equal "0194787400888", messages[0].account_number - assert_equal "0194791600888", messages[1].account_number + assert_equal '0194787400888', messages[0].account_number + assert_equal '0194791600888', messages[1].account_number end - + def test_parsing_a_file_with_broken_structure_should_raise_an_exception - file = File.dirname(__FILE__) + "/fixtures/sepa_snippet_broken.txt" - assert_raise(StandardError) { MT940::CustomerStatementMessage.parse_file(file) } + file = File.dirname(__FILE__) + '/fixtures/sepa_snippet_broken.txt' + assert_raises(StandardError) { MT940::CustomerStatementMessage.parse_file(file) } end - + def test_should_raise_method_missing_when_asking_statement_lines_for_unknown_stuff - file = File.dirname(__FILE__) + "/fixtures/sepa_snippet.txt" + file = File.dirname(__FILE__) + '/fixtures/sepa_snippet.txt' message = MT940::CustomerStatementMessage.parse_file(file).first - assert_raise(NoMethodError) { message.statement_lines.first.foo } + assert_raises(NoMethodError) { message.statement_lines.first.foo } end end diff --git a/test/test_mt940.rb b/test/test_mt940.rb index 869a547..5efa73c 100644 --- a/test/test_mt940.rb +++ b/test/test_mt940.rb @@ -1,39 +1,36 @@ require 'helper' require 'yaml' -#YAML::ENGINE.yamler = 'psych' - +# YAML::ENGINE.yamler = 'psych' # $DEBUG = true -class TestMt940 < Test::Unit::TestCase - +class TestMt940 < Minitest::Test def read_mt940_data(file) MT940.parse(IO.read(file)) end def writeout(name, data) - File.open(name, "w") { |f| f.write data } + File.open(name, 'w') { |f| f.write data } end def test_somthing - #Do nothing for now. + # Do nothing for now. end def x_test_it_should_parse_fixture_files_correctly - Dir[File.dirname(__FILE__) + "/fixtures/*.txt"].reject { |f| f =~ /sepa_snippet/ }.each do |file| + Dir[File.dirname(__FILE__) + '/fixtures/*.txt'].reject { |f| f =~ /sepa_snippet/ }.each do |file| data = read_mt940_data(file) - generated_structure_file = file.gsub(/.txt$/, ".yml") + generated_structure_file = file.gsub(/.txt$/, '.yml') - assert_equal YAML::load_file(generated_structure_file).to_yaml, data.to_yaml + assert_equal YAML.load_file(generated_structure_file).to_yaml, data.to_yaml end end def x_test_it_takes_any_encoding_and_returns_binary - file = File.dirname(__FILE__) + "/fixtures/with_binary_character.txt" - binary_file = MT940.parse(IO.read(file).force_encoding("ISO-8859-15")) - utf8_file = MT940.parse(IO.read(file).force_encoding("UTF-8")) + file = File.dirname(__FILE__) + '/fixtures/with_binary_character.txt' + binary_file = MT940.parse(IO.read(file).force_encoding('ISO-8859-15')) + utf8_file = MT940.parse(IO.read(file).force_encoding('UTF-8')) [binary_file, utf8_file].each do |file| - assert_equal file.last.last.reference.encoding.name, "ISO-8859-1" + assert_equal file.last.last.reference.encoding.name, 'ISO-8859-1' end end - end