diff --git a/README.md b/README.md index f2e8878..caa1d4b 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,9 @@ gem 'cfonb' Below is the list of additional details available for each operation. These details can be accessed through `operation.details`, which will provide all the attributes. To fetch a specific attribute, you can use `operation.details.attribute`. For example, `operation.details.unstructured_label`. Ultimately, you can also access the 70 characters of the detail by using its code like `operation.details.mmo` +All unmapped details can be accessed via `details.unknown` which will return the codes and the corresponding line details. -If you encounter new ones, please open an issue or a pull request with the appropriate implementation. +If you encounter new and relevant ones, please open an issue or a pull request with the appropriate implementation. We aimed at making it as easy as possible to add new details. You just need to do the following on initialization: ```ruby diff --git a/cfonb.gemspec b/cfonb.gemspec index 9949e72..6750406 100644 --- a/cfonb.gemspec +++ b/cfonb.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = 'cfonb' - s.version = '1.0.0' + s.version = '1.1.0' s.required_ruby_version = '>= 3.2' s.summary = 'CFONB parser' s.description = 'An easy to use CFONB format parser' diff --git a/lib/cfonb.rb b/lib/cfonb.rb index ab7e826..91e71f3 100644 --- a/lib/cfonb.rb +++ b/lib/cfonb.rb @@ -33,6 +33,7 @@ require_relative 'cfonb/operation_details/ibe' require_relative 'cfonb/operation_details/npo' require_relative 'cfonb/operation_details/nbu' +require_relative 'cfonb/operation_details/unknown' module CFONB def self.parse(input, optimistic: false) diff --git a/lib/cfonb/operation.rb b/lib/cfonb/operation.rb index 44180d7..4dc18c7 100644 --- a/lib/cfonb/operation.rb +++ b/lib/cfonb/operation.rb @@ -42,8 +42,9 @@ def initialize(line) def merge_detail(line) self.raw += "\n#{line.body}" + operation_details = OperationDetails.for(line) || OperationDetails::Unknown - OperationDetails.for(line)&.apply(details, line) + operation_details.apply(details, line) end def type_code diff --git a/lib/cfonb/operation_details/base.rb b/lib/cfonb/operation_details/base.rb index dcfc7b9..4e2f45d 100644 --- a/lib/cfonb/operation_details/base.rb +++ b/lib/cfonb/operation_details/base.rb @@ -18,6 +18,7 @@ def apply(details, line) details.instance_variable_set(:"@#{line.detail_code}", new_instance) super + return if attributes.include?(:unknown) include_duplicated_code_details(current_details, details) end diff --git a/lib/cfonb/operation_details/unknown.rb b/lib/cfonb/operation_details/unknown.rb new file mode 100644 index 0000000..32ecbf5 --- /dev/null +++ b/lib/cfonb/operation_details/unknown.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module CFONB + module OperationDetails + class Unknown < Base + ATTRIBUTES = %i[unknown].freeze + + def self.apply(details, line) + return unless line.respond_to?(:detail) + + details.unknown ||= {} + code = line.detail_code + + details.unknown[code] = merge_details(details.unknown[code], line.detail) + end + + CFONB::OperationDetails.register('Unknown', self) + end + end +end diff --git a/spec/cfonb/operation_spec.rb b/spec/cfonb/operation_spec.rb index d31a56f..2aff10a 100644 --- a/spec/cfonb/operation_spec.rb +++ b/spec/cfonb/operation_spec.rb @@ -272,6 +272,29 @@ expect(operation.details.ultimate_creditor).to eq('Patrick') end end + + context 'with an unknown detail' do + let(:detail) do + OpenStruct.new( + body: '0530004411001871EUR2 0001016255614090823 AAAEUR200000000000740', + detail_code: 'AAA', + detail: 'EUR200000000000740', + ) + end + + it 'adds the detail to the unknown details hash' do + operation.merge_detail(detail) + + expect(operation.details.unknown).to eq({ 'AAA' => 'EUR200000000000740' }) + end + + it 'updates the current details in case of duplicated codes' do + operation.merge_detail(detail) + operation.merge_detail(detail) + + expect(operation.details.unknown).to eq({ 'AAA' => "EUR200000000000740\nEUR200000000000740" }) + end + end end describe '#type_code' do diff --git a/spec/cfonb/parser_spec.rb b/spec/cfonb/parser_spec.rb index 9925c6b..e9d55c8 100644 --- a/spec/cfonb/parser_spec.rb +++ b/spec/cfonb/parser_spec.rb @@ -49,6 +49,11 @@ exchange_rate: nil, purpose: 'PURPOSE', debtor: 'INTERNET SFR', + unknown: { + 'AAA' => "INTERNETA AAA\nINTERNETA ABB", + 'BBB' => 'INTERNETE BBB', + 'CCC' => 'INTERNETI CCC', + }, ) expect(statements[0].operations[1]).to have_attributes( diff --git a/spec/files/example.txt b/spec/files/example.txt index 21e21d3..c8d728e 100644 --- a/spec/files/example.txt +++ b/spec/files/example.txt @@ -6,6 +6,10 @@ 0515589916200000EUR2 98765432100B1160519 REFREFERENCE 0515589916200000EUR2 98765432100B1160519 RCNOTHER REFERENCE PURPOSE 0515589916200000EUR2 98765432100B1160519 NPYINTERNET SFR +0515589916200000EUR2 98765432100B1160519 AAAINTERNETA AAA +0515589916200000EUR2 98765432100B1160519 AAAINTERNETA ABB +0515589916200000EUR2 98765432100B1160519 BBBINTERNETE BBB +0515589916200000EUR2 98765432100B1160519 CCCINTERNETI CCC 0415589916200000EUR2 98765432100B1160519 160519VIR SEPA DEMONSTRATION 0000000000000000000107}REFERENCE 0515589916200000EUR2 98765432100B1160519 NPYELEC ERDF