sps_king 0.5.0 → 0.6.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +3 -3
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +17 -14
  5. data/gemfiles/{Gemfile-activemodel-6.1.x → Gemfile-activemodel-7.2.x} +1 -1
  6. data/gemfiles/{Gemfile-activemodel-7.0.x → Gemfile-activemodel-8.0.x} +1 -1
  7. data/lib/sps_king/account/address.rb +55 -0
  8. data/lib/sps_king/account/creditor_account.rb +3 -0
  9. data/lib/sps_king/account/creditor_address.rb +2 -34
  10. data/lib/sps_king/account/debtor_account.rb +1 -0
  11. data/lib/sps_king/account/debtor_address.rb +2 -31
  12. data/lib/sps_king/account.rb +3 -0
  13. data/lib/sps_king/converter.rb +14 -10
  14. data/lib/sps_king/message/credit_transfer.rb +114 -111
  15. data/lib/sps_king/message/direct_debit.rb +121 -118
  16. data/lib/sps_king/message.rb +54 -48
  17. data/lib/sps_king/structured_remittance_information.rb +2 -0
  18. data/lib/sps_king/transaction/credit_transfer_transaction.rb +3 -0
  19. data/lib/sps_king/transaction/direct_debit_transaction.rb +9 -6
  20. data/lib/sps_king/transaction.rb +10 -7
  21. data/lib/sps_king/validator.rb +9 -0
  22. data/lib/sps_king/version.rb +3 -1
  23. data/lib/sps_king.rb +1 -0
  24. data/spec/lib/sps_king/account/address_spec.rb +85 -0
  25. data/spec/lib/sps_king/account/creditor_account_spec.rb +14 -13
  26. data/spec/lib/sps_king/account/debtor_account_spec.rb +1 -0
  27. data/spec/lib/sps_king/account_spec.rb +12 -2
  28. data/spec/lib/sps_king/converter_spec.rb +25 -5
  29. data/spec/lib/sps_king/message/credit_transfer_spec.rb +184 -45
  30. data/spec/lib/sps_king/message/direct_debit_spec.rb +218 -102
  31. data/spec/lib/sps_king/message_spec.rb +23 -8
  32. data/spec/lib/sps_king/structured_remittance_information_spec.rb +7 -2
  33. data/spec/lib/sps_king/transaction/credit_transfer_transaction_spec.rb +14 -2
  34. data/spec/lib/sps_king/transaction/direct_debit_transaction_spec.rb +8 -7
  35. data/spec/lib/sps_king/transaction_spec.rb +62 -27
  36. data/spec/lib/sps_king/validator_spec.rb +38 -9
  37. data/spec/spec_helper.rb +8 -4
  38. data/spec/support/active_model.rb +3 -1
  39. data/spec/support/factories.rb +11 -10
  40. data/spec/support/validations.rb +2 -0
  41. data/sps_king.gemspec +1 -0
  42. metadata +8 -12
  43. data/spec/lib/sps_king/account/creditor_address_spec.rb +0 -14
  44. data/spec/lib/sps_king/account/debtor_address_spec.rb +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0bbc6291838df10ef7290cb3e04e1c97d573c92f67e13073e0734743a7d93fa7
4
- data.tar.gz: 9611dd93cbfa199e0d32e50f39f6a9d77c4cc952a64a1d20d191d4644ecb0beb
3
+ metadata.gz: cd8f010271911b78bed9955509277ed10a1a9da20c11ac9cc6c52847cffaf810
4
+ data.tar.gz: 44a38096598ff27e120797c59b43d0505c184db77eb08556982f39ce0823fff4
5
5
  SHA512:
6
- metadata.gz: 7e50e84dac80865f798fe6bbbbfb4582d2500346d87f9e28420a1381c5cc7843db5d8999892fc4d41c34c83fff0cbfd24cf10dafbb13cee6966bac854aa7d59e
7
- data.tar.gz: d6ccf85250954c8e84df1146bf4c59d07d0f0eb99f313fef315bd7e0b4a5a31e8cf204fa4bec4c320d33e289661532346533147b08a9bc60e4ad35828f78ef87
6
+ metadata.gz: 2b88d4094b57f6b40db6ebc5e83b90238bafb99521d38b0c59b5d7b13b317917bf54184fb5b654c810c0cd19394a5915fd6940bc7752fb1a9b9519e9ff0034f3
7
+ data.tar.gz: 99cbcd8f475d7310ecf302a5d6786594d883d8a9464a670baabbaf0207a17227c80dcf46bb277a501649c84c9c957ba126128a58d0cc2047ec4465fc82885e4f
@@ -13,11 +13,11 @@ jobs:
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- ruby: ['3.0', '3.1', '3.2', '3.3']
16
+ ruby: ['3.2', '3.3', '3.4']
17
17
  gemfile:
18
- - gemfiles/Gemfile-activemodel-6.1.x
19
- - gemfiles/Gemfile-activemodel-7.0.x
20
18
  - gemfiles/Gemfile-activemodel-7.1.x
19
+ - gemfiles/Gemfile-activemodel-7.2.x
20
+ - gemfiles/Gemfile-activemodel-8.0.x
21
21
 
22
22
  name: Ruby ${{ matrix.ruby }} / Gemfile {{ matrix.gemfile }}
23
23
 
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## What's Changed in v0.5.0
2
+ * Update covered ruby and activemodel versions for testing
3
+ * Improvement of the convert_decimal function by @casaper in [#14](https://github.com/viafintech/sps_king/pull/14)
4
+ * Standardized creditor and debitor addresses and added stricter validation by @casapar in [#16](https://github.com/viafintech/sps_king/pull/16)
5
+
6
+ **Full Changelog**: https://github.com/viafintech/sps_king/compare/v0.5.0...v0.6.0
7
+
1
8
  ## What's Changed in v0.5.0
2
9
  * Add support for QRR type in structured remittance information by @tobischo in [#10](https://github.com/viafintech/sps_king/pull/10)
3
10
  * Allow structured remittance information optionally for credits
@@ -5,6 +12,8 @@
5
12
  * Add support for QRR as value for proprietary
6
13
  * Fix changelog links
7
14
 
15
+ **Full Changelog**: https://github.com/viafintech/sps_king/compare/v0.4.0...v0.5.0
16
+
8
17
  ## What's Changed in v0.4.0
9
18
  * Bump version to 0.4.0
10
19
  * Make charge bearer optional instead of constant set to `SLEV` by @tobischo in [#7](https://github.com/viafintech/sps_king/pull/7)
data/README.md CHANGED
@@ -22,6 +22,8 @@ This gem is forked of `sepa_king` and therefore heavily inspired by the structur
22
22
 
23
23
  ## Usage
24
24
 
25
+ ## Direct Debit Initiation
26
+
25
27
  How to create the XML for **Direct Debit Initiation** (in German: "Lastschriften")
26
28
 
27
29
  ```ruby
@@ -41,7 +43,7 @@ sdd = SPS::DirectDebit.new(
41
43
 
42
44
  # Creditor Identifier, in German: Gläubiger-Identifikationsnummer
43
45
  # String, max. 35 chars
44
- creditor_identifier: 'ABC1W'
46
+ creditor_identifier: 'ABC1W',
45
47
  )
46
48
 
47
49
  # Second: Add transactions
@@ -84,7 +86,7 @@ sdd.add_transaction(
84
86
  proprietary: 'ESR',
85
87
  # if proprietary is 'ESR': 27 character ISR reference number
86
88
  # if proprietary is 'IPI': 20 character IPI remittance
87
- reference: '609323234234234353453423423'
89
+ reference: '609323234234234353453423423',
88
90
  ),
89
91
 
90
92
  # Service Level
@@ -103,14 +105,14 @@ sdd.add_transaction(
103
105
 
104
106
  # OPTIONAL: Requested collection date, in German "Fälligkeitsdatum der Lastschrift"
105
107
  # Date
106
- requested_date: Date.new(2013,9,5),
108
+ requested_date: Date.new(2013, 9, 5),
107
109
 
108
110
  # OPTIONAL: Use a different creditor account
109
111
  # CreditorAccount
110
112
  creditor_account: SPS::CreditorAccount.new(
111
113
  name: 'Creditor Inc.',
112
114
  iban: 'CH7081232000001998736',
113
- creditor_identifier: '12312'
115
+ creditor_identifier: '12312',
114
116
  )
115
117
 
116
118
  # Specify the country & address of the debtor (The individually required fields depend on the local legal requirements)
@@ -118,11 +120,11 @@ sdd.add_transaction(
118
120
  country_code: 'CH',
119
121
  # Not required if individual fields are used
120
122
  address_line1: 'Mustergasse 123a',
121
- address_line2: '1234 Musterstadt'
123
+ address_line2: '1234 Musterstadt',
122
124
  # Not required if address_line1 and address_line2 are used
123
125
  street_name: 'Mustergasse',
124
126
  post_code: '1234',
125
- town_name: 'Musterstadt'
127
+ town_name: 'Musterstadt',
126
128
  )
127
129
  )
128
130
  sdd.add_transaction ...
@@ -131,6 +133,7 @@ sdd.add_transaction ...
131
133
  xml_string = sdd.to_xml # Use latest schema pain.008.001.02.ch.03
132
134
  ```
133
135
 
136
+ ### Credit Transfer Initiation
134
137
 
135
138
  How to create the XML for **Credit Transfer Initiation** (in German: "Überweisungen")
136
139
 
@@ -147,7 +150,7 @@ sct = SPS::CreditTransfer.new(
147
150
 
148
151
  # International Bank Account Number of the debtor
149
152
  # String, max. 34 chars
150
- iban: 'CH5481230000001998736'
153
+ iban: 'CH5481230000001998736',
151
154
  )
152
155
 
153
156
  # Second: Add transactions
@@ -194,7 +197,7 @@ sct.add_transaction(
194
197
  proprietary: 'QRR',
195
198
  # if proprietary is 'IPI': 20 character IPI remittance
196
199
  # if proprietary is 'QRR': 27 character QR reference
197
- reference: '000008207791225857421286694'
200
+ reference: '000008207791225857421286694',
198
201
  ),
199
202
 
200
203
  # OPTIONAL: Requested execution date, in German "Ausführungstermin"
@@ -209,7 +212,7 @@ sct.add_transaction(
209
212
  # One of these strings:
210
213
  # 'SEPA' ("SEPA-Zahlung")
211
214
  # 'URGP' ("Taggleiche Eilüberweisung")
212
- service_level: 'URGP'
215
+ service_level: 'URGP',
213
216
 
214
217
  # OPTIONAL: Charge Bearer
215
218
  # One of these strings:
@@ -228,12 +231,12 @@ sct.add_transaction(
228
231
  country_code: 'CH',
229
232
  # Not required if individual fields are used
230
233
  address_line1: 'Mustergasse 123a',
231
- address_line2: '1234 Musterstadt'
234
+ address_line2: '1234 Musterstadt',
232
235
  # Not required if address_line1 and address_line2 are used
233
236
  street_name: 'Mustergasse',
234
237
  building_number: '123a',
235
238
  post_code: '1234',
236
- town_name: 'Musterstadt'
239
+ town_name: 'Musterstadt',
237
240
  )
238
241
  )
239
242
  sct.add_transaction ...
@@ -244,12 +247,12 @@ xml_string = sct.to_xml # Use latest schema pain.001.001.03.ch.02
244
247
 
245
248
  ## Changelog
246
249
 
247
- https://github.com/Barzahlen/sps_king/releases
250
+ https://github.com/viafintech/sps_king/releases
248
251
 
249
252
 
250
253
  ## Contributors
251
254
 
252
- https://github.com/Barzahlen/sps_king/graphs/contributors
255
+ https://github.com/viafintech/sps_king/graphs/contributors
253
256
 
254
257
 
255
258
  ## Resources
@@ -262,6 +265,6 @@ https://github.com/Barzahlen/sps_king/graphs/contributors
262
265
 
263
266
  Released under the MIT license
264
267
 
265
- Copyright (c) 2018-2023 Tobias Schoknecht
268
+ Copyright (c) 2018-2025 Tobias Schoknecht
266
269
 
267
270
  Copyright (c) 2013-2017 Georg Leciejewski (Sales King GmbH) & Georg Ledermann for portions of this project copied from sepa_king
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec path: '..'
4
4
 
5
- gem 'activemodel', '~> 6.1.0'
5
+ gem 'activemodel', '~> 7.2.0'
@@ -2,4 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec path: '..'
4
4
 
5
- gem 'activemodel', '~> 7.0.0'
5
+ gem 'activemodel', '~> 8.0.0'
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ module SPS
4
+ class Address
5
+
6
+ include ActiveModel::Validations
7
+ extend Converter
8
+
9
+ attr_accessor :street_name,
10
+ :building_number,
11
+ :post_code,
12
+ :town_name,
13
+ :country_code,
14
+ :address_line1,
15
+ :address_line2
16
+
17
+ convert :street_name, to: :text
18
+ convert :building_number, to: :text
19
+ convert :post_code, to: :text
20
+ convert :town_name, to: :text
21
+ convert :country_code, to: :text
22
+ convert :address_line1, to: :text
23
+ convert :address_line2, to: :text
24
+
25
+ validates :street_name, length: { maximum: 70 }
26
+ validates :building_number, length: { maximum: 16 }
27
+ validates :post_code, length: { maximum: 16 }
28
+ validates :town_name, length: { maximum: 35 }
29
+ validates :address_line1, length: { maximum: 70 }
30
+ validates :address_line2, length: { maximum: 70 }
31
+ validates :country_code,
32
+ presence: true,
33
+ format: { with: /\A[A-Z]{2}\z/ }
34
+ # either town_name or address_line2 must be present
35
+ validates :address_line2, presence: true, if: :town_name_blank?
36
+ validates :town_name, presence: true, if: :address_line2_blank?
37
+
38
+ def initialize(attributes = {})
39
+ attributes.each do |name, value|
40
+ public_send("#{name}=", value)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def town_name_blank?
47
+ town_name.blank?
48
+ end
49
+
50
+ def address_line2_blank?
51
+ address_line2.blank?
52
+ end
53
+
54
+ end
55
+ end
@@ -1,11 +1,14 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class CreditorAccount < Account
5
+
4
6
  attr_accessor :creditor_identifier,
5
7
  :isr_participant_number
6
8
 
7
9
  validates_with CreditorIdentifierValidator,
8
10
  message: "%{value} is invalid"
9
11
  validates_format_of :isr_participant_number, with: /\A\d{9}\z/, allow_nil: true
12
+
10
13
  end
11
14
  end
@@ -1,37 +1,5 @@
1
1
  # encoding: utf-8
2
- module SPS
3
- class CreditorAddress
4
- include ActiveModel::Validations
5
- extend Converter
6
-
7
- attr_accessor :street_name,
8
- :building_number,
9
- :post_code,
10
- :town_name,
11
- :country_code,
12
- :address_line1,
13
- :address_line2
14
-
15
- convert :street_name, to: :text
16
- convert :building_number, to: :text
17
- convert :post_code, to: :text
18
- convert :town_name, to: :text
19
- convert :country_code, to: :text
20
- convert :address_line1, to: :text
21
- convert :address_line2, to: :text
22
2
 
23
- validates_length_of :street_name, maximum: 70
24
- validates_length_of :building_number, maximum: 16
25
- validates_length_of :post_code, maximum: 16
26
- validates_length_of :town_name, maximum: 35
27
- validates_length_of :country_code, is: 2
28
- validates_length_of :address_line1, maximum: 70
29
- validates_length_of :address_line2, maximum: 70
30
-
31
- def initialize(attributes = {})
32
- attributes.each do |name, value|
33
- public_send("#{name}=", value)
34
- end
35
- end
36
- end
3
+ module SPS
4
+ class CreditorAddress < Address; end
37
5
  end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class DebtorAccount < Account
4
5
  end
@@ -1,34 +1,5 @@
1
1
  # encoding: utf-8
2
- module SPS
3
- class DebtorAddress
4
- include ActiveModel::Validations
5
- extend Converter
6
-
7
- attr_accessor :street_name,
8
- :post_code,
9
- :town_name,
10
- :country_code,
11
- :address_line1,
12
- :address_line2
13
-
14
- convert :street_name, to: :text
15
- convert :post_code, to: :text
16
- convert :town_name, to: :text
17
- convert :country_code, to: :text
18
- convert :address_line1, to: :text
19
- convert :address_line2, to: :text
20
2
 
21
- validates_length_of :street_name, maximum: 70
22
- validates_length_of :post_code, maximum: 16
23
- validates_length_of :town_name, maximum: 35
24
- validates_length_of :country_code, is: 2
25
- validates_length_of :address_line1, maximum: 70
26
- validates_length_of :address_line2, maximum: 70
27
-
28
- def initialize(attributes = {})
29
- attributes.each do |name, value|
30
- public_send("#{name}=", value)
31
- end
32
- end
33
- end
3
+ module SPS
4
+ class DebtorAddress < Address; end
34
5
  end
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class Account
5
+
4
6
  include ActiveModel::Validations
5
7
  extend Converter
6
8
 
@@ -20,5 +22,6 @@ module SPS
20
22
  public_send("#{name}=", value)
21
23
  end
22
24
  end
25
+
23
26
  end
24
27
  end
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  module Converter
5
+
4
6
  def convert(*attributes, options)
5
7
  include InstanceMethods
6
8
 
@@ -17,18 +19,19 @@ module SPS
17
19
  end
18
20
 
19
21
  module InstanceMethods
22
+
20
23
  def convert_text(value)
21
24
  return unless value
22
25
 
23
26
  value.to_s.
24
27
  # Replace some special characters described as "Best practices" in Chapter 6.2 of this document:
25
28
  # http://www.europeanpaymentscouncil.eu/index.cfm/knowledge-bank/epc-documents/sepa-requirements-for-an-extended-character-set-unicode-subset-best-practices/
26
- gsub('€','E').
27
- gsub('@','(at)').
28
- gsub('_','-').
29
+ gsub('€', 'E')
30
+ .gsub('@', '(at)')
31
+ .gsub('_', '-').
29
32
 
30
33
  # Replace linebreaks by spaces
31
- gsub(/\n+/,' ').
34
+ gsub(/\n+/, ' ').
32
35
 
33
36
  # Remove all invalid characters
34
37
  gsub(/[^a-zA-Z0-9ÄÖÜäöüß&*$%\ \'\:\?\,\-\(\+\.\)\/]/, '').
@@ -37,17 +40,18 @@ module SPS
37
40
  strip
38
41
  end
39
42
 
43
+ # @param [BigDecimal|Integer|Float|String|nil] value the value to convert
44
+ # @return [BigDecimal|nil] the converted value or nil if the conversion failed
40
45
  def convert_decimal(value)
41
- return unless value
42
- value = begin
46
+ val = begin
43
47
  BigDecimal(value.to_s)
44
48
  rescue ArgumentError
49
+ nil
45
50
  end
46
-
47
- if value && value.finite? && value > 0
48
- value.round(2)
49
- end
51
+ val.round(2) if val&.finite? && val > 0
50
52
  end
53
+
51
54
  end
55
+
52
56
  end
53
57
  end