cmxl 0.1.3 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.mdown +5 -0
- data/cmxl.gemspec +1 -0
- data/lib/cmxl.rb +3 -3
- data/lib/cmxl/field.rb +4 -0
- data/lib/cmxl/fields/{statement_line.rb → transaction.rb} +45 -2
- data/lib/cmxl/statement.rb +39 -8
- data/lib/cmxl/version.rb +1 -1
- data/spec/fields/{statment_line_spec.rb → transaction_spec.rb} +2 -2
- data/spec/fixtures/mt940-deutsche_bank.txt +70 -0
- data/spec/fixtures/mt940-with-detailed-end-balance.txt +8 -0
- data/spec/fixtures/statement-details-mt940.txt +2 -0
- data/spec/fixtures/statement-mt940.txt +1 -0
- data/spec/mt940_parsing_spec.rb +19 -6
- data/spec/spec_helper.rb +2 -2
- data/spec/{transaction_spec.rb → statement_spec.rb} +41 -13
- metadata +31 -9
- data/lib/cmxl/transaction.rb +0 -98
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 42504a4554682fd712473e3e744db2892083965e
         | 
| 4 | 
            +
              data.tar.gz: 3830a7a989cb7f5d490122d2079e67a45dcc75a3
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 4fc0b6927125e065f9c5b9f8c15f2e6ee7d35feb938a72f9bfde9e059e672389e2a00c6e747e81dacf50ca062a8eb1dd39cac7c30272d40fd282022124ddd56a
         | 
| 7 | 
            +
              data.tar.gz: f64a53ecbf51cedbaf80fdcad20a9e0e1aa47bd9780cb05768401d3449756344ad4956e4bb4eaef10bfe2851409b72c95cdc6ba0298582a95a51ce1568c1d766
         | 
    
        data/.rspec
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            --color
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CHANGELOG.mdown
    CHANGED
    
    | @@ -1,3 +1,8 @@ | |
| 1 | 
            +
            # 0.2.0
         | 
| 2 | 
            +
              * added several balance related accessors (#7)
         | 
| 3 | 
            +
              * configuration option for `statement separator` (#5)
         | 
| 4 | 
            +
              * improvement for general compatibility
         | 
| 5 | 
            +
             | 
| 1 6 | 
             
            # 0.1.3
         | 
| 2 7 |  | 
| 3 8 | 
             
              * [BUGFIX] fixed the statement details parser. It failed in case of empty values in the SEPA details
         | 
    
        data/cmxl.gemspec
    CHANGED
    
    | @@ -23,6 +23,7 @@ Gem::Specification.new do |spec| | |
| 23 23 | 
             
              spec.add_development_dependency "bundler", "~> 1.5"
         | 
| 24 24 | 
             
              spec.add_development_dependency "rake"
         | 
| 25 25 | 
             
              spec.add_development_dependency "rspec", '~>3.0'
         | 
| 26 | 
            +
              spec.add_development_dependency "simplecov"
         | 
| 26 27 |  | 
| 27 28 | 
             
              spec.add_dependency "rchardet19"
         | 
| 28 29 | 
             
            end
         | 
    
        data/lib/cmxl.rb
    CHANGED
    
    | @@ -4,14 +4,13 @@ require "rchardet19" | |
| 4 4 |  | 
| 5 5 | 
             
            require 'cmxl/field'
         | 
| 6 6 | 
             
            require 'cmxl/statement'
         | 
| 7 | 
            -
            require 'cmxl/transaction'
         | 
| 8 7 | 
             
            Dir[File.join(File.dirname(__FILE__), 'cmxl/fields', '*.rb')].each { |f| require f; }
         | 
| 9 8 |  | 
| 10 9 | 
             
            module Cmxl
         | 
| 11 10 | 
             
              def self.config
         | 
| 12 11 | 
             
                @config
         | 
| 13 12 | 
             
              end
         | 
| 14 | 
            -
              @config = { :statement_separator => /\n | 
| 13 | 
            +
              @config = { :statement_separator => /\n-\s*\n/m, :raise_line_format_errors => true }
         | 
| 15 14 |  | 
| 16 15 | 
             
              # Public: Parse a MT940 string
         | 
| 17 16 | 
             
              #
         | 
| @@ -27,6 +26,7 @@ module Cmxl | |
| 27 26 | 
             
              # Returns an array of Statement objects
         | 
| 28 27 | 
             
              def self.parse(data, options={})
         | 
| 29 28 | 
             
                options[:universal_newline] ||= true
         | 
| 29 | 
            +
                options[:statement_separator] ||= self.config[:statement_separator]
         | 
| 30 30 | 
             
                # if no encoding is provided we try to guess using CharDet
         | 
| 31 31 | 
             
                if options[:encoding].nil? && cd = CharDet.detect(data, silent: true)
         | 
| 32 32 | 
             
                  options[:encoding] = cd.encoding
         | 
| @@ -38,6 +38,6 @@ module Cmxl | |
| 38 38 | 
             
                  data.encode!('UTF-8', options) if !options.empty?
         | 
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 | 
            -
                data.split( | 
| 41 | 
            +
                data.split(options[:statement_separator]).reject { |s| s.strip.empty? }.collect {|s| Cmxl::Statement.new(s.strip) }
         | 
| 42 42 | 
             
              end
         | 
| 43 43 | 
             
            end
         | 
    
        data/lib/cmxl/field.rb
    CHANGED
    
    
| @@ -1,9 +1,19 @@ | |
| 1 1 | 
             
            module Cmxl
         | 
| 2 2 | 
             
              module Fields
         | 
| 3 | 
            -
                class  | 
| 3 | 
            +
                class Transaction < Field
         | 
| 4 4 | 
             
                  self.tag = 61
         | 
| 5 5 | 
             
                  self.parser = /^(?<date>\d{6})(?<entry_date>\d{4})?(?<funds_code>[a-zA-Z])(?<currency_letter>[a-zA-Z])?(?<amount>\d{1,12},\d{0,2})(?<swift_code>(?:N|F).{3})(?<reference>NONREF|.{0,16})(?:$|\/\/)(?<bank_reference>.*)/i
         | 
| 6 6 |  | 
| 7 | 
            +
                  attr_accessor :details
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def add_meta_data(content)
         | 
| 10 | 
            +
                    self.details = Cmxl::Fields::StatementDetails.parse(content) unless content.nil?
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def sha
         | 
| 14 | 
            +
                    Digest::SHA2.new.update(source).to_s
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 7 17 | 
             
                  def credit?
         | 
| 8 18 | 
             
                    self.data['funds_code'].to_s.upcase == 'C'
         | 
| 9 19 | 
             
                  end
         | 
| @@ -31,8 +41,33 @@ module Cmxl | |
| 31 41 | 
             
                    to_date(self.data['entry_date'], self.date.year) if self.data['entry_date'] && self.date
         | 
| 32 42 | 
             
                  end
         | 
| 33 43 |  | 
| 44 | 
            +
                  # Fields from details
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def description
         | 
| 47 | 
            +
                    details.description if details
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                  def information
         | 
| 50 | 
            +
                    details.information if details
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                  def bic
         | 
| 53 | 
            +
                    details.bic if details
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                  def name
         | 
| 56 | 
            +
                    details.name if details
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                  def iban
         | 
| 59 | 
            +
                    details.iban if details
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                  def sepa
         | 
| 62 | 
            +
                    details.sepa if details
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                  def sub_fields
         | 
| 65 | 
            +
                    details.sub_fields if details
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 34 68 | 
             
                  def to_h
         | 
| 35 69 | 
             
                    {
         | 
| 70 | 
            +
                      'sha' => sha,
         | 
| 36 71 | 
             
                      'date' => date,
         | 
| 37 72 | 
             
                      'entry_date' => entry_date,
         | 
| 38 73 | 
             
                      'amount' => amount,
         | 
| @@ -45,7 +80,15 @@ module Cmxl | |
| 45 80 | 
             
                      'reference' => reference,
         | 
| 46 81 | 
             
                      'bank_reference' => bank_reference,
         | 
| 47 82 | 
             
                      'currency_letter' => currency_letter
         | 
| 48 | 
            -
                    }
         | 
| 83 | 
            +
                    }.merge(details ? details.to_h : {})
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                  def to_hash
         | 
| 87 | 
            +
                    to_h
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  def to_json(*args)
         | 
| 91 | 
            +
                    to_h.to_json(*args)
         | 
| 49 92 | 
             
                  end
         | 
| 50 93 | 
             
                end
         | 
| 51 94 | 
             
              end
         | 
    
        data/lib/cmxl/statement.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            require 'digest/sha2'
         | 
| 2 2 | 
             
            module Cmxl
         | 
| 3 3 | 
             
              class Statement
         | 
| 4 | 
            -
                attr_accessor :source, :collection, : | 
| 4 | 
            +
                attr_accessor :source, :collection, :fields, :lines
         | 
| 5 5 |  | 
| 6 6 | 
             
                # Public: Initiate a new Statement and parse a provided single statement string
         | 
| 7 7 | 
             
                # It directly parses the source and initiates file and transaction objects.
         | 
| @@ -13,10 +13,13 @@ module Cmxl | |
| 13 13 | 
             
                  self.source = source
         | 
| 14 14 | 
             
                  self.fields = []
         | 
| 15 15 | 
             
                  self.lines = []
         | 
| 16 | 
            -
                  self.transactions = []
         | 
| 17 16 | 
             
                  self.parse!
         | 
| 18 17 | 
             
                end
         | 
| 19 18 |  | 
| 19 | 
            +
                def transactions
         | 
| 20 | 
            +
                  self.fields.select { |field| field.kind_of?(Fields::Transaction) }
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 20 23 | 
             
                # Internal: Parse a single MT940 statement and extract the line data
         | 
| 21 24 | 
             
                #
         | 
| 22 25 | 
             
                def parse!
         | 
| @@ -28,17 +31,33 @@ module Cmxl | |
| 28 31 | 
             
                      self.lines.last << line.strip
         | 
| 29 32 | 
             
                    end
         | 
| 30 33 | 
             
                  end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  self. | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 34 | 
            +
             | 
| 35 | 
            +
                  self.fields = []
         | 
| 36 | 
            +
                  lines.each do |line|
         | 
| 37 | 
            +
                    if line.match(/\A:86:/)
         | 
| 38 | 
            +
                      if field = fields.last
         | 
| 39 | 
            +
                        field.add_meta_data(line)
         | 
| 40 | 
            +
                      end
         | 
| 37 41 | 
             
                    else
         | 
| 38 42 | 
             
                      field = Field.parse(line)
         | 
| 39 43 | 
             
                      self.fields << field unless field.nil?
         | 
| 40 44 | 
             
                    end
         | 
| 41 45 | 
             
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  # puts "Fixed Fields"
         | 
| 48 | 
            +
                  # puts fields.inspect
         | 
| 49 | 
            +
                  #
         | 
| 50 | 
            +
                  # # Now we check each line for its content ans structure it for further use. If it is part of a transaction we initate or update a transaction else we parse the field and add it to the fields collection
         | 
| 51 | 
            +
                  # self.lines.each do |line|
         | 
| 52 | 
            +
                  #   if line.match(/\A:61:/)
         | 
| 53 | 
            +
                  #     self.transactions << Cmxl::Transaction.new(line)
         | 
| 54 | 
            +
                  #   elsif line.match(/\A:86:/) && !self.transactions.last.nil?
         | 
| 55 | 
            +
                  #     self.transactions.last.details = line
         | 
| 56 | 
            +
                  #   else
         | 
| 57 | 
            +
                  #     field = Field.parse(line)
         | 
| 58 | 
            +
                  #     self.fields << field unless field.nil?
         | 
| 59 | 
            +
                  #   end
         | 
| 60 | 
            +
                  # end
         | 
| 42 61 | 
             
                end
         | 
| 43 62 |  | 
| 44 63 | 
             
                # Public: SHA2 of the provided source
         | 
| @@ -65,14 +84,26 @@ module Cmxl | |
| 65 84 | 
             
                  self.field(60, 'F')
         | 
| 66 85 | 
             
                end
         | 
| 67 86 |  | 
| 87 | 
            +
                def opening_or_intermediary_balance
         | 
| 88 | 
            +
                  self.field(60)
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 68 91 | 
             
                def closing_balance
         | 
| 69 92 | 
             
                  self.field(62, 'F')
         | 
| 70 93 | 
             
                end
         | 
| 71 94 |  | 
| 95 | 
            +
                def closing_or_intermediary_balance
         | 
| 96 | 
            +
                  self.field(62)
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 72 99 | 
             
                def available_balance
         | 
| 73 100 | 
             
                  self.field(64)
         | 
| 74 101 | 
             
                end
         | 
| 75 102 |  | 
| 103 | 
            +
                def legal_sequence_number
         | 
| 104 | 
            +
                  self.field(28).source
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 76 107 | 
             
                def to_h
         | 
| 77 108 | 
             
                  {
         | 
| 78 109 | 
             
                    'reference' => reference,
         | 
    
        data/lib/cmxl/version.rb
    CHANGED
    
    
| @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            describe Cmxl::Fields:: | 
| 3 | 
            +
            describe Cmxl::Fields::Transaction do
         | 
| 4 4 |  | 
| 5 | 
            -
              subject { Cmxl::Fields:: | 
| 5 | 
            +
              subject { Cmxl::Fields::Transaction.parse(fixture_line(:statement_line)) }
         | 
| 6 6 |  | 
| 7 7 | 
             
              it { expect(subject.date).to eql(Date.new(2014,9,1)) }
         | 
| 8 8 | 
             
              it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            :20:131110
         | 
| 2 | 
            +
            :25:45050050/76198810
         | 
| 3 | 
            +
            :28:27/01
         | 
| 4 | 
            +
            :60F:C131016DEM84349,74
         | 
| 5 | 
            +
            :61:131017D6800,NCHK16703074
         | 
| 6 | 
            +
            :86:999PN5477SCHECK-NR. 0000016703074
         | 
| 7 | 
            +
            :61:131017D620,3NSTON
         | 
| 8 | 
            +
            :86:999PN0911DAUERAUFTR.NR. 14
         | 
| 9 | 
            +
            :61:131017C18500,NCLRN
         | 
| 10 | 
            +
            :86:999PN2406SCHECK
         | 
| 11 | 
            +
            :61:131015D14220,NBOEN
         | 
| 12 | 
            +
            :86:999PN0920WECHSEL
         | 
| 13 | 
            +
            :61:131017D1507,NTRFN
         | 
| 14 | 
            +
            :86:999PN0920SCHNELLUEB
         | 
| 15 | 
            +
            :61:131024C4200,NMSCN
         | 
| 16 | 
            +
            :86:999PN2506AUSSENH. NR. 1
         | 
| 17 | 
            +
            :61:131017D19900,NTRFN
         | 
| 18 | 
            +
            :86:999PN0907UEBERTRAG
         | 
| 19 | 
            +
            :61:131017D400,NTRFN
         | 
| 20 | 
            +
            :86:999PN0891BTX
         | 
| 21 | 
            +
            :61:131018C3656,74NMSCN
         | 
| 22 | 
            +
            :86:999PN0850EINZAHLG.N
         | 
| 23 | 
            +
            :61:131019C23040,NMSCN
         | 
| 24 | 
            +
            :86:999PN0812LT.ANLAGE
         | 
| 25 | 
            +
            :61:131027D5862,14NCHKN
         | 
| 26 | 
            +
            :86:999PN5329AUSLSCHECK
         | 
| 27 | 
            +
            :62F:C131017DEM84437,04
         | 
| 28 | 
            +
            -
         | 
| 29 | 
            +
            :20:1234567
         | 
| 30 | 
            +
            :21:9876543210
         | 
| 31 | 
            +
            :25:10020030/1234567
         | 
| 32 | 
            +
            :28C:5/1
         | 
| 33 | 
            +
            :60F:C021101EUR2187,95
         | 
| 34 | 
            +
            :61:0211011102DR800,NSTONONREF//55555
         | 
| 35 | 
            +
            :86:008?00DAUERAUFTRAG?100599?20Miete November?3010020030?31234567?32MUELLER?34339
         | 
| 36 | 
            +
            :61:0211021102CR3000,NTRFNONREF//55555
         | 
| 37 | 
            +
            :86:051?00UEBERWEISUNG?100599?20Gehalt Oktob
         | 
| 38 | 
            +
            er
         | 
| 39 | 
            +
            ?21Firma
         | 
| 40 | 
            +
            Mustermann
         | 
| 41 | 
            +
            GmbH?3050060400?31084756
         | 
| 42 | 
            +
            4700?32MUELLER?34339
         | 
| 43 | 
            +
            :62F:C021131EUR4387,95
         | 
| 44 | 
            +
            -
         | 
| 45 | 
            +
            :20:TELEWIZORY S.A.
         | 
| 46 | 
            +
            :25:BPHKPLPK/320000546101
         | 
| 47 | 
            +
            :28C:00084/001
         | 
| 48 | 
            +
            :60F:C031002PLN40000,00
         | 
| 49 | 
            +
            :61:0310201020C20000,00FMSCNONREF//8327000090031789
         | 
| 50 | 
            +
            Card transaction
         | 
| 51 | 
            +
            :86: 020?00Wyplata-(dysp/przel)?2008106000760000777777777777?2115617?
         | 
| 52 | 
            +
            22INFO INFO INFO INFO INFO INFO 1 END?23INFO INFO INFO INFO INFO
         | 
| 53 | 
            +
            INFO 2 END?24ZAPLATA ZA FABRYKATY DO TUB?25 - 200 S ZTUK, TRANZY
         | 
| 54 | 
            +
            STORY-?26300 SZT GR544 I OPORNIKI-5?2700 SZT GTX847 FAKTURA 333/
         | 
| 55 | 
            +
            2?28003.?3010600076?310000777777777777?32HUTA SZKLA TOPIC UL
         | 
| 56 | 
            +
            PRZEMY?33SLOWA 67 32-669 WROCLAW?38PL081060007600007777777
         | 
| 57 | 
            +
            77777
         | 
| 58 | 
            +
            :61:0310201020D10000,00FTRFREF 25611247//8327000090031790
         | 
| 59 | 
            +
            Transfer
         | 
| 60 | 
            +
            :86: 020?00Wyplata-(dysp/przel)?2008106000760000777777777777?2115617?
         | 
| 61 | 
            +
            22INFO INFO INFO INFO INFO INFO 1 END?23INFO INFO INFO INFO INFO
         | 
| 62 | 
            +
            INFO 2 END?24ZAPLATA ZA FABRYKATY DO TUB?25 - 200 S ZTUK, TRANZY
         | 
| 63 | 
            +
            STORY-?26300 SZT GR544 I OPORNIKI-5?2700 SZT GTX847 FAKTURA 333/
         | 
| 64 | 
            +
            2?28003.?3010600076?310000777777777777?38PL081060007600007777777
         | 
| 65 | 
            +
            77777
         | 
| 66 | 
            +
            :61:0310201020C40,00FTRFNONREF//8327000090031791
         | 
| 67 | 
            +
            Interest credit
         | 
| 68 | 
            +
            :86: 844?00Uznanie kwotą odsetek?20Odsetki od lokaty nr 101000?21022086
         | 
| 69 | 
            +
            :62F:C020325PLN50040,00 
         | 
| 70 | 
            +
            -
         | 
| @@ -0,0 +1,8 @@ | |
| 1 | 
            +
            :20:STARTUMS
         | 
| 2 | 
            +
            :25:45050050/76198810
         | 
| 3 | 
            +
            :28C:00001/00001
         | 
| 4 | 
            +
            :60F:C160101EUR10,00
         | 
| 5 | 
            +
            :61:1601010222CR1,00NTRFNONREF//CT16-01-01-08.32
         | 
| 6 | 
            +
            :86:008?00DAUERAUFTRAG?100599?20Miete Dezember?3010020030?31234567?32MUELLER?34339
         | 
| 7 | 
            +
            :62F:C160222EUR15,00
         | 
| 8 | 
            +
            :86:Some random addition to it
         | 
| @@ -0,0 +1,2 @@ | |
| 1 | 
            +
            :61:1409010902DR000000000001,62NTRF0000549855700010//025498557/000001
         | 
| 2 | 
            +
            :86:171?00SEPA LASTSCHRIFT KUNDE?10281?20KREF+EREF+TRX-0A4A47C3-F846-4729?21-8A1B-5DF620F?22MREF+CAC97D2144174318AC18D9?23BF815BD4FB?24CRED+DE98ZZZ09999999999?25SVWZ+FOO TRX-0A4A47C3-F84?266-4729-8A1B-5DF620F?30HYVEDEMMXXX?31HUkkbbbsssskcccccccccccccccx?32Peter Pan?99?34171
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            :61:1409010902DR000000000001,62NTRF0000549855700010//025498557/000001
         | 
    
        data/spec/mt940_parsing_spec.rb
    CHANGED
    
    | @@ -1,11 +1,10 @@ | |
| 1 1 | 
             
            # encoding: utf-8
         | 
| 2 | 
            -
             | 
| 3 2 | 
             
            require 'spec_helper'
         | 
| 4 3 |  | 
| 5 4 | 
             
            describe 'parsing a statement' do
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
              context 'ISO 8859-1' do
         | 
| 8 6 | 
             
                subject { Cmxl.parse(mt940_file('mt940-iso8859-1'))[0] }
         | 
| 7 | 
            +
             | 
| 9 8 | 
             
                it { expect(subject.reference).to eql('1234567') }
         | 
| 10 9 | 
             
                it { expect(subject.opening_balance.amount_in_cents).to eql(218795) }
         | 
| 11 10 | 
             
                it { expect(subject.closing_balance.amount_in_cents).to eql(438795) }
         | 
| @@ -17,12 +16,12 @@ describe 'parsing a statement' do | |
| 17 16 |  | 
| 18 17 | 
             
              context 'first example' do
         | 
| 19 18 | 
             
                subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[0] }
         | 
| 19 | 
            +
             | 
| 20 20 | 
             
                it { expect(subject.reference).to eql('131110') }
         | 
| 21 21 | 
             
                it { expect(subject.opening_balance.amount_in_cents).to eql(8434974) }
         | 
| 22 22 | 
             
                it { expect(subject.closing_balance.amount_in_cents).to eql(8443704) }
         | 
| 23 23 | 
             
                it { expect(subject.generation_date).to eql(Date.new(2013, 11, 10)) }
         | 
| 24 24 | 
             
                it { expect(subject.transactions.count).to eql(11) }
         | 
| 25 | 
            -
             | 
| 26 25 | 
             
                it { expect(subject.transactions.first.description).to eql('PN5477SCHECK-NR. 0000016703074') }
         | 
| 27 26 | 
             
                it { expect(subject.transactions.first.information).to eql('PN5477SCHECK-NR. 0000016703074') }
         | 
| 28 27 | 
             
                it { expect(subject.transactions.first.sepa).to eql({}) }
         | 
| @@ -31,6 +30,7 @@ describe 'parsing a statement' do | |
| 31 30 |  | 
| 32 31 | 
             
              context 'second example' do
         | 
| 33 32 | 
             
                subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[1] }
         | 
| 33 | 
            +
             | 
| 34 34 | 
             
                it { expect(subject.reference).to eql('1234567') }
         | 
| 35 35 | 
             
                it { expect(subject.opening_balance.amount_in_cents).to eql(218795) }
         | 
| 36 36 | 
             
                it { expect(subject.closing_balance.amount_in_cents).to eql(438795) }
         | 
| @@ -44,10 +44,9 @@ describe 'parsing a statement' do | |
| 44 44 | 
             
                it { expect(subject.transactions.first.iban).to eql('234567') }
         | 
| 45 45 | 
             
              end
         | 
| 46 46 |  | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 47 | 
             
              context 'third example' do
         | 
| 50 48 | 
             
                subject { Cmxl.parse(mt940_file(), :encoding => 'ISO-8859-1', :universal_newline => true)[2] }
         | 
| 49 | 
            +
             | 
| 51 50 | 
             
                it { expect(subject.reference).to eql('TELEWIZORY S.A.') }
         | 
| 52 51 | 
             
                it { expect(subject.opening_balance.amount_in_cents).to eql(4000000) }
         | 
| 53 52 | 
             
                it { expect(subject.closing_balance.amount_in_cents).to eql(5004000) }
         | 
| @@ -59,7 +58,21 @@ describe 'parsing a statement' do | |
| 59 58 | 
             
                it { expect(subject.transactions.first.bic).to eql('10600076') }
         | 
| 60 59 | 
             
                it { expect(subject.transactions.first.iban).to eql('PL08106000760000777777777777') }
         | 
| 61 60 | 
             
                it { expect(subject.transactions.first.sepa).to eql({}) }
         | 
| 62 | 
            -
            end
         | 
| 61 | 
            +
              end
         | 
| 63 62 |  | 
| 63 | 
            +
              context 'statement separator as used by most banks' do
         | 
| 64 | 
            +
                subject { Cmxl.parse(mt940_file('mt940')) }
         | 
| 64 65 |  | 
| 66 | 
            +
                it 'detects all statements by default' do
         | 
| 67 | 
            +
                  expect(subject.size).to eq(3)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              context 'statement separator as used by Deutsche Bank' do
         | 
| 72 | 
            +
                subject { Cmxl.parse(mt940_file('mt940-deutsche_bank')) }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                it 'detects all statements by default' do
         | 
| 75 | 
            +
                  expect(subject.size).to eq(3)
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 65 78 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    
| @@ -1,17 +1,17 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            describe Cmxl | 
| 3 | 
            +
            describe Cmxl do
         | 
| 4 4 |  | 
| 5 5 | 
             
              context 'with details' do
         | 
| 6 | 
            -
                subject { Cmxl | 
| 6 | 
            +
                subject { Cmxl.parse( mt940_file('statement-details-mt940') ).first.transactions.first }
         | 
| 7 | 
            +
             | 
| 7 8 | 
             
                it { expect(subject).to be_debit }
         | 
| 8 9 | 
             
                it { expect(subject).to_not be_credit }
         | 
| 9 10 | 
             
                it { expect(subject.funds_code).to eql('D') }
         | 
| 10 | 
            -
                it { expect(subject.date).to eql(Date.new(2014,9,1))}
         | 
| 11 | 
            -
                it { expect(subject.entry_date).to eql(Date.new(2014,9,2))}
         | 
| 12 | 
            -
                it { expect(subject.amount).to eql(1.62)}
         | 
| 13 | 
            -
                it { expect(subject. | 
| 14 | 
            -
                it { expect(subject.amount_in_cents).to eql(162)}
         | 
| 11 | 
            +
                it { expect(subject.date).to eql(Date.new(2014,9,1)) }
         | 
| 12 | 
            +
                it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
         | 
| 13 | 
            +
                it { expect(subject.amount).to eql(1.62) }
         | 
| 14 | 
            +
                it { expect(subject.amount_in_cents).to eql(162) }
         | 
| 15 15 | 
             
                it { expect(subject.to_h).to eql(
         | 
| 16 16 | 
             
                  {
         | 
| 17 17 | 
             
                    "date" => Date.new(2014,9,1),
         | 
| @@ -63,14 +63,42 @@ describe Cmxl::Transaction do | |
| 63 63 | 
             
              end
         | 
| 64 64 |  | 
| 65 65 | 
             
              context 'without details' do
         | 
| 66 | 
            -
                subject { Cmxl | 
| 66 | 
            +
                subject { Cmxl.parse( mt940_file('statement-mt940') ).first.transactions.first }
         | 
| 67 | 
            +
             | 
| 67 68 | 
             
                it { expect(subject).to be_debit }
         | 
| 68 69 | 
             
                it { expect(subject).to_not be_credit }
         | 
| 69 70 | 
             
                it { expect(subject.date).to eql(Date.new(2014,9,1))}
         | 
| 70 | 
            -
                it { expect(subject.entry_date).to eql(Date.new(2014,9,2))}
         | 
| 71 | 
            -
                it { expect(subject.amount).to eql(1.62)}
         | 
| 72 | 
            -
                it { expect(subject.amount_in_cents).to eql(162)}
         | 
| 73 | 
            -
                it  | 
| 74 | 
            -
             | 
| 71 | 
            +
                it { expect(subject.entry_date).to eql(Date.new(2014,9,2)) }
         | 
| 72 | 
            +
                it { expect(subject.amount).to eql(1.62) }
         | 
| 73 | 
            +
                it { expect(subject.amount_in_cents).to eql(162) }
         | 
| 74 | 
            +
                it 'does not include any details in its hash representation' do
         | 
| 75 | 
            +
                  expect(subject.to_h).to eql({
         | 
| 76 | 
            +
                    "date" => Date.new(2014,9,1),
         | 
| 77 | 
            +
                    "sha" => "3c5e65aa3d3878b06b58b6f1ae2f3693004dfb04e3ab7119a1c1244e612293da",
         | 
| 78 | 
            +
                    "entry_date"=>Date.new(2014,9,2),
         | 
| 79 | 
            +
                    "funds_code" => "D",
         | 
| 80 | 
            +
                    "currency_letter" => "R",
         | 
| 81 | 
            +
                    "amount" => 1.62,
         | 
| 82 | 
            +
                    "swift_code" => "NTRF",
         | 
| 83 | 
            +
                    "reference" => "0000549855700010",
         | 
| 84 | 
            +
                    "bank_reference" => "025498557/000001",
         | 
| 85 | 
            +
                    "amount_in_cents" => 162,
         | 
| 86 | 
            +
                    "sign" => -1,
         | 
| 87 | 
            +
                    "debit" => true,
         | 
| 88 | 
            +
                    "credit" => false
         | 
| 89 | 
            +
                  })
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
              describe 'statement with detailed end balance' do
         | 
| 94 | 
            +
                subject { Cmxl.parse( mt940_file('mt940-with-detailed-end-balance') ).first.transactions.first }
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                it 'includes correct iban' do
         | 
| 97 | 
            +
                  expect(subject.iban).to eq('234567')
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                it 'includes correct bic' do
         | 
| 101 | 
            +
                  expect(subject.bic).to eq('10020030')
         | 
| 102 | 
            +
                end
         | 
| 75 103 | 
             
              end
         | 
| 76 104 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cmxl
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Michael Bumann
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2016- | 
| 11 | 
            +
            date: 2016-11-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -52,6 +52,20 @@ dependencies: | |
| 52 52 | 
             
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '3.0'
         | 
| 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'
         | 
| 62 | 
            +
              type: :development
         | 
| 63 | 
            +
              prerelease: false
         | 
| 64 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 | 
            +
                requirements:
         | 
| 66 | 
            +
                - - ">="
         | 
| 67 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            +
                    version: '0'
         | 
| 55 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 70 | 
             
              name: rchardet19
         | 
| 57 71 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -75,6 +89,7 @@ extensions: [] | |
| 75 89 | 
             
            extra_rdoc_files: []
         | 
| 76 90 | 
             
            files:
         | 
| 77 91 | 
             
            - ".gitignore"
         | 
| 92 | 
            +
            - ".rspec"
         | 
| 78 93 | 
             
            - ".travis.yml"
         | 
| 79 94 | 
             
            - CHANGELOG.mdown
         | 
| 80 95 | 
             
            - Gemfile
         | 
| @@ -90,10 +105,9 @@ files: | |
| 90 105 | 
             
            - lib/cmxl/fields/closing_balance.rb
         | 
| 91 106 | 
             
            - lib/cmxl/fields/reference.rb
         | 
| 92 107 | 
             
            - lib/cmxl/fields/statement_details.rb
         | 
| 93 | 
            -
            - lib/cmxl/fields/statement_line.rb
         | 
| 94 108 | 
             
            - lib/cmxl/fields/statement_number.rb
         | 
| 109 | 
            +
            - lib/cmxl/fields/transaction.rb
         | 
| 95 110 | 
             
            - lib/cmxl/statement.rb
         | 
| 96 | 
            -
            - lib/cmxl/transaction.rb
         | 
| 97 111 | 
             
            - lib/cmxl/version.rb
         | 
| 98 112 | 
             
            - spec/field_spec.rb
         | 
| 99 113 | 
             
            - spec/fields/account_balance_spec.rb
         | 
| @@ -103,7 +117,7 @@ files: | |
| 103 117 | 
             
            - spec/fields/reference_spec.rb
         | 
| 104 118 | 
             
            - spec/fields/statement_details_spec.rb
         | 
| 105 119 | 
             
            - spec/fields/statement_number_spec.rb
         | 
| 106 | 
            -
            - spec/fields/ | 
| 120 | 
            +
            - spec/fields/transaction_spec.rb
         | 
| 107 121 | 
             
            - spec/fields/unknown_spec.rb
         | 
| 108 122 | 
             
            - spec/fixtures/lines/account_balance_credit.txt
         | 
| 109 123 | 
             
            - spec/fixtures/lines/account_balance_debit.txt
         | 
| @@ -115,12 +129,16 @@ files: | |
| 115 129 | 
             
            - spec/fixtures/lines/statement_details.txt
         | 
| 116 130 | 
             
            - spec/fixtures/lines/statement_line.txt
         | 
| 117 131 | 
             
            - spec/fixtures/lines/statement_number.txt
         | 
| 132 | 
            +
            - spec/fixtures/mt940-deutsche_bank.txt
         | 
| 118 133 | 
             
            - spec/fixtures/mt940-iso8859-1.txt
         | 
| 134 | 
            +
            - spec/fixtures/mt940-with-detailed-end-balance.txt
         | 
| 119 135 | 
             
            - spec/fixtures/mt940.txt
         | 
| 136 | 
            +
            - spec/fixtures/statement-details-mt940.txt
         | 
| 137 | 
            +
            - spec/fixtures/statement-mt940.txt
         | 
| 120 138 | 
             
            - spec/mt940_parsing_spec.rb
         | 
| 121 139 | 
             
            - spec/spec_helper.rb
         | 
| 140 | 
            +
            - spec/statement_spec.rb
         | 
| 122 141 | 
             
            - spec/support/fixtures.rb
         | 
| 123 | 
            -
            - spec/transaction_spec.rb
         | 
| 124 142 | 
             
            homepage: https://github.com/railslove/cmxl
         | 
| 125 143 | 
             
            licenses:
         | 
| 126 144 | 
             
            - MIT
         | 
| @@ -143,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 143 161 | 
             
                  version: '0'
         | 
| 144 162 | 
             
            requirements: []
         | 
| 145 163 | 
             
            rubyforge_project: 
         | 
| 146 | 
            -
            rubygems_version: 2. | 
| 164 | 
            +
            rubygems_version: 2.5.1
         | 
| 147 165 | 
             
            signing_key: 
         | 
| 148 166 | 
             
            specification_version: 4
         | 
| 149 167 | 
             
            summary: Cmxl is your friendly MT940 bank statement parser
         | 
| @@ -156,7 +174,7 @@ test_files: | |
| 156 174 | 
             
            - spec/fields/reference_spec.rb
         | 
| 157 175 | 
             
            - spec/fields/statement_details_spec.rb
         | 
| 158 176 | 
             
            - spec/fields/statement_number_spec.rb
         | 
| 159 | 
            -
            - spec/fields/ | 
| 177 | 
            +
            - spec/fields/transaction_spec.rb
         | 
| 160 178 | 
             
            - spec/fields/unknown_spec.rb
         | 
| 161 179 | 
             
            - spec/fixtures/lines/account_balance_credit.txt
         | 
| 162 180 | 
             
            - spec/fixtures/lines/account_balance_debit.txt
         | 
| @@ -168,9 +186,13 @@ test_files: | |
| 168 186 | 
             
            - spec/fixtures/lines/statement_details.txt
         | 
| 169 187 | 
             
            - spec/fixtures/lines/statement_line.txt
         | 
| 170 188 | 
             
            - spec/fixtures/lines/statement_number.txt
         | 
| 189 | 
            +
            - spec/fixtures/mt940-deutsche_bank.txt
         | 
| 171 190 | 
             
            - spec/fixtures/mt940-iso8859-1.txt
         | 
| 191 | 
            +
            - spec/fixtures/mt940-with-detailed-end-balance.txt
         | 
| 172 192 | 
             
            - spec/fixtures/mt940.txt
         | 
| 193 | 
            +
            - spec/fixtures/statement-details-mt940.txt
         | 
| 194 | 
            +
            - spec/fixtures/statement-mt940.txt
         | 
| 173 195 | 
             
            - spec/mt940_parsing_spec.rb
         | 
| 174 196 | 
             
            - spec/spec_helper.rb
         | 
| 197 | 
            +
            - spec/statement_spec.rb
         | 
| 175 198 | 
             
            - spec/support/fixtures.rb
         | 
| 176 | 
            -
            - spec/transaction_spec.rb
         | 
    
        data/lib/cmxl/transaction.rb
    DELETED
    
    | @@ -1,98 +0,0 @@ | |
| 1 | 
            -
            module Cmxl
         | 
| 2 | 
            -
              class Transaction
         | 
| 3 | 
            -
                attr_accessor :statement_line, :details
         | 
| 4 | 
            -
             | 
| 5 | 
            -
                def initialize(statement_line, details = nil)
         | 
| 6 | 
            -
                  self.statement_line = statement_line
         | 
| 7 | 
            -
                  self.details = details
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                def statement_line=(line)
         | 
| 11 | 
            -
                  @statement_line = Cmxl::Fields::StatementLine.parse(line) unless line.nil?
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                def details=(line)
         | 
| 15 | 
            -
                  @details = Cmxl::Fields::StatementDetails.parse(line) unless line.nil?
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                def sha
         | 
| 19 | 
            -
                  Digest::SHA2.new.update(self.statement_line.source).to_s
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                def debit?
         | 
| 23 | 
            -
                  self.statement_line.debit?
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
                def credit?
         | 
| 26 | 
            -
                  self.statement_line.credit?
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
                def amount
         | 
| 29 | 
            -
                  self.statement_line.amount
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
                def sign
         | 
| 32 | 
            -
                  self.statement_line.sign
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
                def funds_code
         | 
| 35 | 
            -
                  self.statement_line.funds_code
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
                def amount_in_cents
         | 
| 38 | 
            -
                  self.statement_line.amount_in_cents
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
                def date
         | 
| 41 | 
            -
                  self.statement_line.date
         | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
                def entry_date
         | 
| 44 | 
            -
                  self.statement_line.entry_date
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
                def funds_code
         | 
| 47 | 
            -
                  self.statement_line.funds_code
         | 
| 48 | 
            -
                end
         | 
| 49 | 
            -
                def currency_letter
         | 
| 50 | 
            -
                  self.statement_line.currency_letter
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
                def swift_code
         | 
| 53 | 
            -
                  self.statement_line.swift_code
         | 
| 54 | 
            -
                end
         | 
| 55 | 
            -
                def reference
         | 
| 56 | 
            -
                  self.statement_line.reference
         | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
                def bank_reference
         | 
| 59 | 
            -
                  self.statement_line.bank_reference
         | 
| 60 | 
            -
                end
         | 
| 61 | 
            -
                def description
         | 
| 62 | 
            -
                  self.details.description if self.details
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
                def information
         | 
| 65 | 
            -
                  self.details.information if self.details
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
                def bic
         | 
| 68 | 
            -
                  self.details.bic if self.details
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
                def name
         | 
| 71 | 
            -
                  self.details.name if self.details
         | 
| 72 | 
            -
                end
         | 
| 73 | 
            -
                def iban
         | 
| 74 | 
            -
                  self.details.iban if self.details
         | 
| 75 | 
            -
                end
         | 
| 76 | 
            -
                def sepa
         | 
| 77 | 
            -
                  self.details.sepa if self.details
         | 
| 78 | 
            -
                end
         | 
| 79 | 
            -
                def sub_fields
         | 
| 80 | 
            -
                  self.details.sub_fields if self.details
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                def to_h
         | 
| 84 | 
            -
                  {}.tap do |h|
         | 
| 85 | 
            -
                    h['sha'] = self.sha
         | 
| 86 | 
            -
                    h.merge!(self.statement_line.to_h)
         | 
| 87 | 
            -
                    h.merge!(self.details.to_h) if self.details
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
                def to_hash
         | 
| 91 | 
            -
                  to_h
         | 
| 92 | 
            -
                end
         | 
| 93 | 
            -
                def to_json(*args)
         | 
| 94 | 
            -
                  to_h.to_json(*args)
         | 
| 95 | 
            -
                end
         | 
| 96 | 
            -
              end
         | 
| 97 | 
            -
             | 
| 98 | 
            -
            end
         |