norma43_parser 2.1.1 → 4.0.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/.github/workflows/ci.yml +22 -0
- data/.github/workflows/release.yml +33 -0
- data/CHANGELOG.md +19 -10
- data/Gemfile +2 -2
- data/Gemfile.lock +52 -34
- data/README.md +2 -0
- data/lib/norma43/models/account/spanish_iban.rb +107 -0
- data/lib/norma43/models/account.rb +31 -0
- data/lib/norma43/models/additional_currency.rb +16 -0
- data/lib/norma43/models/additional_item.rb +15 -0
- data/lib/norma43/models/document.rb +23 -0
- data/lib/norma43/models/transaction.rb +25 -0
- data/lib/norma43/models.rb +0 -76
- data/lib/norma43/version.rb +1 -1
- data/norma43_parser.gemspec +3 -5
- data/spec/example1_parse_spec.rb +1 -1
- data/spec/norma43/models/account/spanish_iban_spec.rb +107 -0
- data/spec/norma43/models/account_spec.rb +20 -0
- metadata +19 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0449ec18860a4308816374b89703797ec359a8032b15a3f3fb3e4a8749dbdc44'
|
|
4
|
+
data.tar.gz: 0d0438fb23ba70c0b5c3ce107e7ac6e71dd5007ceb2fe64887aaf0d61c46cf60
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd5abd1c1b2893eb6fcb8c2025d659c1c5876198d68d624e19e18ac1975aecb48c557f7a27070c690f0090028d630a6d2ece30daf7daad70eda3993a736e56fe
|
|
7
|
+
data.tar.gz: 5431b59a68a1f3ce474e31aa44735ad9a6c1863deb20e157375e8b81938192d99e6184f587b6eadefffd992bf6fd5398acea5e261d2100f70be4bd59d4b019f3
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Ruby CI
|
|
2
|
+
|
|
3
|
+
on: [ pull_request, push ]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
ruby-version: ["3.3", "3.2", "3.1", "3.0", "jruby-head"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v2
|
|
16
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
17
|
+
uses: ruby/setup-ruby@v1
|
|
18
|
+
with:
|
|
19
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
20
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
21
|
+
- name: Run tests
|
|
22
|
+
run: bundle exec rspec
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Create gem release pull request
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- 'master'
|
|
6
|
+
jobs:
|
|
7
|
+
release:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: GoogleCloudPlatform/release-please-action@v3
|
|
11
|
+
id: release
|
|
12
|
+
with:
|
|
13
|
+
release-type: ruby
|
|
14
|
+
package-name: norma43_parser
|
|
15
|
+
bump-minor-pre-major: true
|
|
16
|
+
version-file: 'lib/norma43/version.rb'
|
|
17
|
+
- uses: actions/checkout@v2
|
|
18
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
19
|
+
- uses: ruby/setup-ruby@v1
|
|
20
|
+
with:
|
|
21
|
+
ruby-version: 3.2
|
|
22
|
+
if: ${{ steps.release.outputs.release_created }}
|
|
23
|
+
- name: Publish gem to Rubygems
|
|
24
|
+
run: |
|
|
25
|
+
mkdir -p $HOME/.gem
|
|
26
|
+
touch $HOME/.gem/credentials
|
|
27
|
+
chmod 0600 $HOME/.gem/credentials
|
|
28
|
+
printf -- "---\n:rubygems: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
29
|
+
gem build *.gemspec
|
|
30
|
+
gem push --KEY rubygems --host https://rubygems.org *.gem
|
|
31
|
+
env:
|
|
32
|
+
GEM_HOST_API_KEY: "${{ secrets.RUBYGEMS_PUBLISH_TOKEN }}"
|
|
33
|
+
if: ${{ steps.release.outputs.release_created }}
|
data/CHANGELOG.md
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
|
-
##
|
|
1
|
+
## [4.0.0](https://github.com/sequra/norma43_parser/compare/3.0.0...v4.0.0) (2024-06-18)
|
|
2
2
|
|
|
3
|
-
### Breaking Changes
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
### ⚠ BREAKING CHANGES
|
|
5
|
+
|
|
6
|
+
* Drop Ruby support below 3
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* Get IBANs from account instances ([#15](https://github.com/sequra/norma43_parser/issues/15)) ([c69d162](https://github.com/sequra/norma43_parser/commit/c69d162361b188f2b2d904b1958e3108be9a3939))
|
|
11
|
+
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
## v3.0.0 (2021-12-15)
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
### Breaking Changes
|
|
16
|
+
|
|
17
|
+
- Drop Ruby support below 2.6.
|
|
18
|
+
|
|
19
|
+
## v2.1.1 (2020-03-13)
|
|
10
20
|
|
|
11
21
|
### Enhancements
|
|
12
22
|
|
|
13
23
|
- Update rake requirement from ~> 10.0 to ~> 13.0 (#6)
|
|
14
24
|
|
|
15
|
-
##
|
|
25
|
+
## v2.0.0 (2019-10-17)
|
|
16
26
|
|
|
17
27
|
### Breaking Changes
|
|
18
28
|
|
|
19
29
|
- Drop Ruby support below 2.4.
|
|
20
30
|
|
|
21
|
-
### Bug fixes
|
|
22
|
-
|
|
23
|
-
-
|
|
24
31
|
|
|
25
32
|
### Enhancements
|
|
26
33
|
|
|
27
34
|
- Clean up dependencies
|
|
28
35
|
|
|
29
|
-
##
|
|
36
|
+
## v1.0.1 (2016-02-16)
|
|
37
|
+
|
|
38
|
+
- Initial release
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
norma43_parser (
|
|
4
|
+
norma43_parser (4.0.0)
|
|
5
5
|
virtus (~> 1.0)
|
|
6
6
|
zeitwerk (~> 2.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
|
-
ast (2.4.
|
|
11
|
+
ast (2.4.2)
|
|
12
12
|
axiom-types (0.1.1)
|
|
13
13
|
descendants_tracker (~> 0.0.4)
|
|
14
14
|
ice_nine (~> 0.11.0)
|
|
@@ -17,57 +17,75 @@ GEM
|
|
|
17
17
|
descendants_tracker (~> 0.0.1)
|
|
18
18
|
descendants_tracker (0.0.4)
|
|
19
19
|
thread_safe (~> 0.3, >= 0.3.1)
|
|
20
|
-
diff-lcs (1.
|
|
20
|
+
diff-lcs (1.5.1)
|
|
21
21
|
equalizer (0.0.11)
|
|
22
22
|
ice_nine (0.11.2)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
json (2.7.2)
|
|
24
|
+
json (2.7.2-java)
|
|
25
|
+
language_server-protocol (3.17.0.3)
|
|
26
|
+
parallel (1.25.1)
|
|
27
|
+
parser (3.3.3.0)
|
|
28
|
+
ast (~> 2.4.1)
|
|
29
|
+
racc
|
|
30
|
+
racc (1.8.0)
|
|
31
|
+
racc (1.8.0-java)
|
|
32
|
+
rainbow (3.1.1)
|
|
33
|
+
rake (13.2.1)
|
|
34
|
+
regexp_parser (2.9.2)
|
|
35
|
+
rexml (3.3.0)
|
|
36
|
+
strscan
|
|
37
|
+
rspec (3.13.0)
|
|
38
|
+
rspec-core (~> 3.13.0)
|
|
39
|
+
rspec-expectations (~> 3.13.0)
|
|
40
|
+
rspec-mocks (~> 3.13.0)
|
|
41
|
+
rspec-core (3.13.0)
|
|
42
|
+
rspec-support (~> 3.13.0)
|
|
43
|
+
rspec-expectations (3.13.0)
|
|
36
44
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
37
|
-
rspec-support (~> 3.
|
|
38
|
-
rspec-mocks (3.
|
|
45
|
+
rspec-support (~> 3.13.0)
|
|
46
|
+
rspec-mocks (3.13.1)
|
|
39
47
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
40
|
-
rspec-support (~> 3.
|
|
41
|
-
rspec-support (3.
|
|
42
|
-
rubocop (
|
|
43
|
-
|
|
48
|
+
rspec-support (~> 3.13.0)
|
|
49
|
+
rspec-support (3.13.1)
|
|
50
|
+
rubocop (1.64.1)
|
|
51
|
+
json (~> 2.3)
|
|
52
|
+
language_server-protocol (>= 3.17.0)
|
|
44
53
|
parallel (~> 1.10)
|
|
45
|
-
parser (>= 2
|
|
54
|
+
parser (>= 3.3.0.2)
|
|
46
55
|
rainbow (>= 2.2.2, < 4.0)
|
|
56
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
57
|
+
rexml (>= 3.2.5, < 4.0)
|
|
58
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
|
47
59
|
ruby-progressbar (~> 1.7)
|
|
48
|
-
unicode-display_width (>=
|
|
49
|
-
rubocop-
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
|
61
|
+
rubocop-ast (1.31.3)
|
|
62
|
+
parser (>= 3.3.1.0)
|
|
63
|
+
rubocop-performance (1.21.0)
|
|
64
|
+
rubocop (>= 1.48.1, < 2.0)
|
|
65
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
|
66
|
+
ruby-progressbar (1.13.0)
|
|
67
|
+
strscan (3.1.0)
|
|
68
|
+
strscan (3.1.0-java)
|
|
52
69
|
thread_safe (0.3.6)
|
|
53
|
-
|
|
70
|
+
thread_safe (0.3.6-java)
|
|
71
|
+
unicode-display_width (2.5.0)
|
|
54
72
|
virtus (1.0.5)
|
|
55
73
|
axiom-types (~> 0.1)
|
|
56
74
|
coercible (~> 1.0)
|
|
57
75
|
descendants_tracker (~> 0.0, >= 0.0.3)
|
|
58
76
|
equalizer (~> 0.0, >= 0.0.9)
|
|
59
|
-
zeitwerk (2.
|
|
77
|
+
zeitwerk (2.6.15)
|
|
60
78
|
|
|
61
79
|
PLATFORMS
|
|
80
|
+
java
|
|
62
81
|
ruby
|
|
63
82
|
|
|
64
83
|
DEPENDENCIES
|
|
65
|
-
bundler (~> 1.0)
|
|
66
84
|
norma43_parser!
|
|
67
85
|
rake (~> 13.0)
|
|
68
|
-
rspec (~> 3.
|
|
69
|
-
rubocop (
|
|
70
|
-
rubocop-performance
|
|
86
|
+
rspec (~> 3.9)
|
|
87
|
+
rubocop (~> 1)
|
|
88
|
+
rubocop-performance (~> 1)
|
|
71
89
|
|
|
72
90
|
BUNDLED WITH
|
|
73
|
-
|
|
91
|
+
2.4.22
|
data/README.md
CHANGED
|
@@ -49,6 +49,8 @@ information_mode_code=3,
|
|
|
49
49
|
transactions=[transaction1..transactionN]
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
Also, accounts know their full IBAN. For the example above, `#iban` returns `"ES5400810054180001234567"`.
|
|
53
|
+
|
|
52
54
|
### Transaction
|
|
53
55
|
|
|
54
56
|
The transaction object has all the information described in the standard format and may include a maximum of five additional items.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Norma43
|
|
4
|
+
module Models
|
|
5
|
+
class Account
|
|
6
|
+
class SpanishIban
|
|
7
|
+
COUNTRY_CODE = "ES"
|
|
8
|
+
BANK_CODE_RANGE = BRANCH_CODE_RANGE = 0..9999
|
|
9
|
+
MAX_BANK_CODE_SIZE = MAX_BRANCH_CODE_SIZE = 4
|
|
10
|
+
ACCOUNT_NUMBER_RANGE = 0..9_999_999_999
|
|
11
|
+
IBAN_MODULUS = 97
|
|
12
|
+
IBAN_FORMAT_STRING = "%{country_code}%<checksum_number>02d%{ccc}"
|
|
13
|
+
CCC_MODULUS = 11
|
|
14
|
+
CCC_FORMAT_STRING = "%<bank_code>04d%<branch_code>04d%<checksum_number>02d%<account_number>010d"
|
|
15
|
+
CCC_WEIGHTS = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1].freeze # Sorted by order of magnitude: units, tens, hundreds, etc.
|
|
16
|
+
|
|
17
|
+
def self.from_account(account)
|
|
18
|
+
return nil unless valid_numbers?(account.bank_code, account.branch_code, account.account_number)
|
|
19
|
+
|
|
20
|
+
new(
|
|
21
|
+
bank_code: account.bank_code,
|
|
22
|
+
branch_code: account.branch_code,
|
|
23
|
+
account_number: account.account_number
|
|
24
|
+
).to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(bank_code:, branch_code:, account_number:)
|
|
28
|
+
@bank_code, @branch_code, @account_number =
|
|
29
|
+
if self.class.valid_numbers?(bank_code, branch_code, account_number)
|
|
30
|
+
[bank_code, branch_code, account_number]
|
|
31
|
+
else
|
|
32
|
+
[nil, nil, nil]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def to_s
|
|
37
|
+
return "" if [bank_code, branch_code, account_number].any?(nil)
|
|
38
|
+
|
|
39
|
+
iban
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
attr_reader :bank_code, :branch_code, :account_number
|
|
44
|
+
|
|
45
|
+
def self.valid_numbers?(bank_code, branch_code, account_number)
|
|
46
|
+
return false unless BANK_CODE_RANGE.include?(bank_code)
|
|
47
|
+
return false unless BRANCH_CODE_RANGE.include?(branch_code)
|
|
48
|
+
return false unless ACCOUNT_NUMBER_RANGE.include?(account_number)
|
|
49
|
+
true
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def iban
|
|
53
|
+
format_string = IBAN_FORMAT_STRING
|
|
54
|
+
country_code = COUNTRY_CODE
|
|
55
|
+
country_number = calculate_country_number
|
|
56
|
+
ccc = calculate_ccc
|
|
57
|
+
number = "#{ccc}#{country_number}00".to_i
|
|
58
|
+
checksum_number = calculate_iban_checksum_number(number)
|
|
59
|
+
|
|
60
|
+
sprintf(format_string,
|
|
61
|
+
country_code: country_code,
|
|
62
|
+
checksum_number: checksum_number,
|
|
63
|
+
ccc: ccc)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def calculate_country_number
|
|
67
|
+
COUNTRY_CODE.chars.map { |char| char.to_i(36) }.join
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def calculate_ccc
|
|
71
|
+
format_string = CCC_FORMAT_STRING
|
|
72
|
+
bank_with_branch_number = (bank_code * 10**MAX_BRANCH_CODE_SIZE) + branch_code
|
|
73
|
+
|
|
74
|
+
bank_with_branch_check_digit, account_number_check_digit = [
|
|
75
|
+
bank_with_branch_number, account_number
|
|
76
|
+
].map { |number| calculate_spanish_checksum_digit(number) }
|
|
77
|
+
|
|
78
|
+
checksum_number = bank_with_branch_check_digit * 10 + account_number_check_digit
|
|
79
|
+
|
|
80
|
+
sprintf(format_string,
|
|
81
|
+
bank_code: bank_code,
|
|
82
|
+
branch_code: branch_code,
|
|
83
|
+
checksum_number: checksum_number,
|
|
84
|
+
account_number: account_number)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def calculate_spanish_checksum_digit(number)
|
|
88
|
+
modulus = CCC_MODULUS
|
|
89
|
+
|
|
90
|
+
reminder = CCC_WEIGHTS.map.with_index { |weight, order_of_magnitude|
|
|
91
|
+
digit_at_position = (number / 10**order_of_magnitude) % 10
|
|
92
|
+
|
|
93
|
+
digit_at_position * weight
|
|
94
|
+
}.sum % modulus
|
|
95
|
+
|
|
96
|
+
return reminder if reminder.zero? || reminder == 1
|
|
97
|
+
modulus - reminder
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def calculate_iban_checksum_number(number)
|
|
101
|
+
modulus = IBAN_MODULUS
|
|
102
|
+
(modulus + 1) - (number % modulus)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "virtus"
|
|
4
|
+
|
|
5
|
+
module Norma43
|
|
6
|
+
module Models
|
|
7
|
+
class Account
|
|
8
|
+
include Virtus.model
|
|
9
|
+
|
|
10
|
+
attribute :bank_code
|
|
11
|
+
attribute :branch_code
|
|
12
|
+
attribute :account_number
|
|
13
|
+
attribute :start_date
|
|
14
|
+
attribute :end_date
|
|
15
|
+
attribute :balance_code
|
|
16
|
+
attribute :balance_amount
|
|
17
|
+
attribute :currency_code
|
|
18
|
+
attribute :information_mode_code
|
|
19
|
+
attribute :abbreviated_name
|
|
20
|
+
attribute :debit_entries
|
|
21
|
+
attribute :debit_amount
|
|
22
|
+
attribute :credit_entries
|
|
23
|
+
attribute :credit_amount
|
|
24
|
+
attribute :transactions, Array[Transaction]
|
|
25
|
+
|
|
26
|
+
def iban
|
|
27
|
+
@iban ||= SpanishIban.from_account(self)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "virtus"
|
|
4
|
+
|
|
5
|
+
module Norma43
|
|
6
|
+
module Models
|
|
7
|
+
class AdditionalCurrency
|
|
8
|
+
include Virtus.model
|
|
9
|
+
|
|
10
|
+
attribute :data_code
|
|
11
|
+
attribute :currency_code
|
|
12
|
+
attribute :amount
|
|
13
|
+
attribute :free
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "virtus"
|
|
4
|
+
|
|
5
|
+
module Norma43
|
|
6
|
+
module Models
|
|
7
|
+
class Document
|
|
8
|
+
include Virtus.model
|
|
9
|
+
|
|
10
|
+
attribute :id
|
|
11
|
+
attribute :created_at
|
|
12
|
+
attribute :delivery_number
|
|
13
|
+
attribute :file_type
|
|
14
|
+
attribute :name
|
|
15
|
+
attribute :number_of_lines
|
|
16
|
+
attribute :accounts, Array[Account]
|
|
17
|
+
|
|
18
|
+
def transaction_date
|
|
19
|
+
accounts.map(&:date).compact.first
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "virtus"
|
|
4
|
+
|
|
5
|
+
module Norma43
|
|
6
|
+
module Models
|
|
7
|
+
class Transaction
|
|
8
|
+
include Virtus.model
|
|
9
|
+
|
|
10
|
+
attribute :origin_branch_code
|
|
11
|
+
attribute :transaction_date
|
|
12
|
+
attribute :value_date
|
|
13
|
+
attribute :shared_item
|
|
14
|
+
attribute :own_item
|
|
15
|
+
attribute :amount_code
|
|
16
|
+
attribute :amount
|
|
17
|
+
attribute :document_number
|
|
18
|
+
attribute :reference_1
|
|
19
|
+
attribute :reference_2
|
|
20
|
+
attribute :additional_items, Array[AdditionalItem]
|
|
21
|
+
attribute :additional_currency, AdditionalCurrency
|
|
22
|
+
def debit?; self.amount_code == DEBIT_CODE end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/norma43/models.rb
CHANGED
|
@@ -4,83 +4,7 @@ require "virtus"
|
|
|
4
4
|
|
|
5
5
|
module Norma43
|
|
6
6
|
module Models
|
|
7
|
-
# forward declarations
|
|
8
|
-
class Account; end
|
|
9
|
-
class Transaction; end
|
|
10
|
-
class AdditionalItem; end
|
|
11
|
-
class AdditionalCurrency; end
|
|
12
7
|
DEBIT_CODE = 1
|
|
13
8
|
CREDIT_CODE = 2
|
|
14
|
-
|
|
15
|
-
class Document
|
|
16
|
-
include Virtus.model
|
|
17
|
-
|
|
18
|
-
attribute :id
|
|
19
|
-
attribute :created_at
|
|
20
|
-
attribute :delivery_number
|
|
21
|
-
attribute :file_type
|
|
22
|
-
attribute :name
|
|
23
|
-
attribute :number_of_lines
|
|
24
|
-
attribute :accounts, Array[Account]
|
|
25
|
-
|
|
26
|
-
def transaction_date
|
|
27
|
-
accounts.map(&:date).compact.first
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
class Account
|
|
32
|
-
include Virtus.model
|
|
33
|
-
|
|
34
|
-
attribute :bank_code
|
|
35
|
-
attribute :branch_code
|
|
36
|
-
attribute :account_number
|
|
37
|
-
attribute :start_date
|
|
38
|
-
attribute :end_date
|
|
39
|
-
attribute :balance_code
|
|
40
|
-
attribute :balance_amount
|
|
41
|
-
attribute :currency_code
|
|
42
|
-
attribute :information_mode_code
|
|
43
|
-
attribute :abbreviated_name
|
|
44
|
-
attribute :debit_entries
|
|
45
|
-
attribute :debit_amount
|
|
46
|
-
attribute :credit_entries
|
|
47
|
-
attribute :credit_amount
|
|
48
|
-
attribute :transactions, Array[Transaction]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
class Transaction
|
|
52
|
-
include Virtus.model
|
|
53
|
-
|
|
54
|
-
attribute :origin_branch_code
|
|
55
|
-
attribute :transaction_date
|
|
56
|
-
attribute :value_date
|
|
57
|
-
attribute :shared_item
|
|
58
|
-
attribute :own_item
|
|
59
|
-
attribute :amount_code
|
|
60
|
-
attribute :amount
|
|
61
|
-
attribute :document_number
|
|
62
|
-
attribute :reference_1
|
|
63
|
-
attribute :reference_2
|
|
64
|
-
attribute :additional_items, Array[AdditionalItem]
|
|
65
|
-
attribute :additional_currency, AdditionalCurrency
|
|
66
|
-
def debit?; self.amount_code == DEBIT_CODE end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
class AdditionalItem
|
|
70
|
-
include Virtus.model
|
|
71
|
-
|
|
72
|
-
attribute :data_code
|
|
73
|
-
attribute :item_1
|
|
74
|
-
attribute :item_2
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class AdditionalCurrency
|
|
78
|
-
include Virtus.model
|
|
79
|
-
|
|
80
|
-
attribute :data_code
|
|
81
|
-
attribute :currency_code
|
|
82
|
-
attribute :amount
|
|
83
|
-
attribute :free
|
|
84
|
-
end
|
|
85
9
|
end
|
|
86
10
|
end
|
data/lib/norma43/version.rb
CHANGED
data/norma43_parser.gemspec
CHANGED
|
@@ -13,17 +13,15 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
spec.homepage = "https://github.com/sequra/norma43_parser"
|
|
14
14
|
spec.license = "MIT"
|
|
15
15
|
|
|
16
|
-
spec.required_ruby_version = "
|
|
16
|
+
spec.required_ruby_version = ">= 3.0"
|
|
17
17
|
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0")
|
|
19
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
20
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
21
20
|
spec.require_paths = ["lib"]
|
|
22
21
|
|
|
23
22
|
spec.add_runtime_dependency "virtus", "~> 1.0"
|
|
24
23
|
spec.add_runtime_dependency "zeitwerk", "~> 2.0"
|
|
25
24
|
|
|
26
|
-
spec.add_development_dependency "
|
|
27
|
-
spec.add_development_dependency "
|
|
28
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
|
29
27
|
end
|
data/spec/example1_parse_spec.rb
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Norma43
|
|
4
|
+
module Models
|
|
5
|
+
class Account
|
|
6
|
+
RSpec.describe SpanishIban do
|
|
7
|
+
def build_account(**attributes)
|
|
8
|
+
instance_double(Account, **attributes)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe ".from_account" do
|
|
12
|
+
subject(:iban) { described_class.from_account(account) }
|
|
13
|
+
|
|
14
|
+
context "with the example in the documentation" do
|
|
15
|
+
let(:account) { build_account(bank_code: 81, branch_code: 54, account_number: 1234567) }
|
|
16
|
+
it { is_expected.to eq("ES5400810054180001234567") }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context "with the account from the example1.n43 fixture" do
|
|
20
|
+
let(:account) {
|
|
21
|
+
file.seek 2
|
|
22
|
+
bank_code = file.read(4).to_i
|
|
23
|
+
branch_code = file.read(4).to_i
|
|
24
|
+
account_number = file.read(10).to_i
|
|
25
|
+
|
|
26
|
+
build_account(bank_code: bank_code, branch_code: branch_code, account_number: account_number)
|
|
27
|
+
}
|
|
28
|
+
let(:file) { File.open(File.join(__dir__, "../../../fixtures/example1.n43"), encoding: "iso-8859-1") }
|
|
29
|
+
|
|
30
|
+
it { is_expected.to eq("ES1799991111710123456789") }
|
|
31
|
+
|
|
32
|
+
after { file.close }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "with minimal edge-case" do
|
|
36
|
+
let(:account) { build_account(bank_code: 3, branch_code: 0, account_number: 0) }
|
|
37
|
+
it { is_expected.to eq("ES8700030000300000000000") }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "with extreme edge-case" do
|
|
41
|
+
let(:account) { build_account(bank_code: 9000, branch_code: 9999, account_number: 9999999999) }
|
|
42
|
+
it { is_expected.to eq("ES3790009999309999999999") }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#to_s" do
|
|
47
|
+
subject { described_class.new(bank_code: 0, branch_code: 0, account_number: 0) }
|
|
48
|
+
|
|
49
|
+
it { is_expected.to(respond_to(:to_s)) }
|
|
50
|
+
|
|
51
|
+
context "with incorrect account values" do
|
|
52
|
+
subject { described_class.new(bank_code: bank_code, branch_code: branch_code, account_number: account_number).to_s }
|
|
53
|
+
|
|
54
|
+
let(:bank_code) { 9999 }
|
|
55
|
+
let(:branch_code) { 1111 }
|
|
56
|
+
let(:account_number) { 123456789 }
|
|
57
|
+
|
|
58
|
+
context "with missing bank code" do
|
|
59
|
+
let(:bank_code) { nil }
|
|
60
|
+
it { is_expected.to be_empty }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "with missing branch code" do
|
|
64
|
+
let(:branch_code) { nil }
|
|
65
|
+
it { is_expected.to be_empty }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "with missing account number" do
|
|
69
|
+
let(:account_number) { nil }
|
|
70
|
+
it { is_expected.to be_empty }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "with negative bank code" do
|
|
74
|
+
let(:bank_code) { -3 }
|
|
75
|
+
it { is_expected.to be_empty }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "with negative branch code" do
|
|
79
|
+
let(:bank_code) { -1 }
|
|
80
|
+
it { is_expected.to be_empty }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "with negative account number" do
|
|
84
|
+
let(:account_number) { -123456789 }
|
|
85
|
+
it { is_expected.to be_empty }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context "with more than 4 digits in the bank code" do
|
|
89
|
+
let(:bank_code) { 99990 }
|
|
90
|
+
it { is_expected.to be_empty }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "with more than 4 digits in the branch code" do
|
|
94
|
+
let(:bank_code) { 11110 }
|
|
95
|
+
it { is_expected.to be_empty }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context "with more than 10 digits in the account number" do
|
|
99
|
+
let(:account_number) { 12345678900 }
|
|
100
|
+
it { is_expected.to be_empty }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Norma43
|
|
4
|
+
module Models
|
|
5
|
+
RSpec.describe Account do
|
|
6
|
+
describe "#iban" do
|
|
7
|
+
it { is_expected.to respond_to :iban }
|
|
8
|
+
|
|
9
|
+
context "with the example in the documentation" do
|
|
10
|
+
it "delegates to SpanishIban to return a IBAN string" do
|
|
11
|
+
account = subject
|
|
12
|
+
allow(Account::SpanishIban).to receive(:from_account).with(account).and_return("ES0000000000000000000123")
|
|
13
|
+
expect(account.iban).to eq("ES0000000000000000000123")
|
|
14
|
+
expect(Account::SpanishIban).to have_received(:from_account).with(account)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: norma43_parser
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 4.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sequra engineering
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-06-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: virtus
|
|
@@ -38,20 +38,6 @@ dependencies:
|
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '2.0'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: bundler
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: '1.0'
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: '1.0'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
42
|
name: rake
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -72,14 +58,14 @@ dependencies:
|
|
|
72
58
|
requirements:
|
|
73
59
|
- - "~>"
|
|
74
60
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '3.
|
|
61
|
+
version: '3.9'
|
|
76
62
|
type: :development
|
|
77
63
|
prerelease: false
|
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
65
|
requirements:
|
|
80
66
|
- - "~>"
|
|
81
67
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '3.
|
|
68
|
+
version: '3.9'
|
|
83
69
|
description:
|
|
84
70
|
email:
|
|
85
71
|
- dev@sequra.es
|
|
@@ -89,6 +75,8 @@ extra_rdoc_files: []
|
|
|
89
75
|
files:
|
|
90
76
|
- ".github/ISSUE_TEMPLATE.md"
|
|
91
77
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
|
78
|
+
- ".github/workflows/ci.yml"
|
|
79
|
+
- ".github/workflows/release.yml"
|
|
92
80
|
- ".rubocop.yml"
|
|
93
81
|
- CHANGELOG.md
|
|
94
82
|
- Gemfile
|
|
@@ -111,6 +99,12 @@ files:
|
|
|
111
99
|
- lib/norma43/line_parsers/transaction.rb
|
|
112
100
|
- lib/norma43/line_processors.rb
|
|
113
101
|
- lib/norma43/models.rb
|
|
102
|
+
- lib/norma43/models/account.rb
|
|
103
|
+
- lib/norma43/models/account/spanish_iban.rb
|
|
104
|
+
- lib/norma43/models/additional_currency.rb
|
|
105
|
+
- lib/norma43/models/additional_item.rb
|
|
106
|
+
- lib/norma43/models/document.rb
|
|
107
|
+
- lib/norma43/models/transaction.rb
|
|
114
108
|
- lib/norma43/parser.rb
|
|
115
109
|
- lib/norma43/utils/contexts.rb
|
|
116
110
|
- lib/norma43/utils/string_helpers.rb
|
|
@@ -133,6 +127,8 @@ files:
|
|
|
133
127
|
- spec/norma43/line_processors/document_end_spec.rb
|
|
134
128
|
- spec/norma43/line_processors/document_start_spec.rb
|
|
135
129
|
- spec/norma43/line_processors/transaction_spec.rb
|
|
130
|
+
- spec/norma43/models/account/spanish_iban_spec.rb
|
|
131
|
+
- spec/norma43/models/account_spec.rb
|
|
136
132
|
- spec/norma43/parser_spec.rb
|
|
137
133
|
- spec/norma43_spec.rb
|
|
138
134
|
- spec/spec_helper.rb
|
|
@@ -147,16 +143,16 @@ require_paths:
|
|
|
147
143
|
- lib
|
|
148
144
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
145
|
requirements:
|
|
150
|
-
- - "
|
|
146
|
+
- - ">="
|
|
151
147
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: '
|
|
148
|
+
version: '3.0'
|
|
153
149
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
150
|
requirements:
|
|
155
151
|
- - ">="
|
|
156
152
|
- !ruby/object:Gem::Version
|
|
157
153
|
version: '0'
|
|
158
154
|
requirements: []
|
|
159
|
-
rubygems_version: 3.
|
|
155
|
+
rubygems_version: 3.4.19
|
|
160
156
|
signing_key:
|
|
161
157
|
specification_version: 4
|
|
162
158
|
summary: Parses banks transactions files specified in rule 43
|
|
@@ -177,6 +173,8 @@ test_files:
|
|
|
177
173
|
- spec/norma43/line_processors/document_end_spec.rb
|
|
178
174
|
- spec/norma43/line_processors/document_start_spec.rb
|
|
179
175
|
- spec/norma43/line_processors/transaction_spec.rb
|
|
176
|
+
- spec/norma43/models/account/spanish_iban_spec.rb
|
|
177
|
+
- spec/norma43/models/account_spec.rb
|
|
180
178
|
- spec/norma43/parser_spec.rb
|
|
181
179
|
- spec/norma43_spec.rb
|
|
182
180
|
- spec/spec_helper.rb
|