sepa_king 0.1.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 72f5b41884bc29b3dfe4032b8973d0b4f99fce20
4
- data.tar.gz: 49097e2be968e3ac86c9660214d18512a9d289b6
3
+ metadata.gz: c78e42fd31151e02569f9f54ee43fc82691ba3f9
4
+ data.tar.gz: 100d813077c65787e992689fe15eede1a7424f3d
5
5
  SHA512:
6
- metadata.gz: f17e0ff69c50df21d785deb0b92d57f2c16ad34c3fe9ba4a828032d01322b1dba0f705207cf843ed166bad6d13129a91388b2991373fa2f7199e48d7c5c20614
7
- data.tar.gz: 626b15c006d37daa9bb4882c2cf973efd6fae25f0d595ca202edc42e81fe129fbf14260de7452caafa1c370e9d8099c1569ed7937d601728e275afe1e1af0145
6
+ metadata.gz: 7a1c98624cd47da6dfaffe4aa498a6a35f24c22b74abfc1f0f8fdb442c2603bea00a381df53ee6a9ef0fdd2d5d7fff32c366d7d49c4e95f22993fa5640079b1f
7
+ data.tar.gz: d72486654271db57e2a778cc396ec0183d998949eb19646720fbb4131e0ce2eb62901f4f807a4acecc3e88db471b9ce6bdbac4765c8779fda10f200fcd81b9bc
data/.travis.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  rvm:
2
2
  - 1.9.3
3
3
  - 2.0.0
4
+ - 2.1.0
data/README.md CHANGED
@@ -23,7 +23,7 @@ BTW: **pain** is a shortcut for **Pa**yment **In**itiation.
23
23
 
24
24
  ## Requirements
25
25
 
26
- * Ruby 1.9.3 or 2.0.0
26
+ * Ruby 1.9.3 or newer
27
27
 
28
28
 
29
29
  ## Installation
@@ -194,6 +194,36 @@ xml_string = sct.to_xml # Use latest schema pain.001.003.03
194
194
  xml_string = sct.to_xml('pain.001.002.03') # Use former schema pain.001.002.03
195
195
  ```
196
196
 
197
+ ## Validations
198
+
199
+ You can rely on our internal validations, raising errors when needed, during
200
+ message creation.
201
+ To validate your models holding SEPA related information (e.g. BIC, IBAN,
202
+ mandate_id) you can use our validator classes or rely on some constants.
203
+
204
+ Examples:
205
+
206
+ ```ruby
207
+ class BankAccount < ActiveRecord::Base
208
+ # IBAN validation, by default it validates the attribute named "iban"
209
+ validates_with SEPA::IBANValidator, field_name: :iban_the_terrible
210
+
211
+ # BIC validation, by default it validates the attribute named "bic"
212
+ validates_with SEPA::BICValidator, field_name: :bank_bic
213
+ end
214
+
215
+ class Payment < ActiveRecord::Base
216
+ validates_inclusion_of :sepa_sequence_type, in: SEPA::DirectDebitTransaction::SEQUENCE_TYPES
217
+
218
+ # Mandate ID validation, by default it validates the attribute named "mandate_id"
219
+ validates_with SEPA::MandateIdentifierValidator, field_name: :mandate_id
220
+ end
221
+ ```
222
+
223
+ Also see:
224
+ * [lib/sepa_king/validator.rb](https://github.com/salesking/sepa_king/blob/master/lib/sepa_king/validator.rb)
225
+ * [lib/sepa_king/transaction/direct_debit_transaction.rb](https://github.com/salesking/sepa_king/blob/master/lib/sepa_king/transaction/direct_debit_transaction.rb)
226
+
197
227
 
198
228
  ## Changelog
199
229
 
@@ -13,7 +13,7 @@ module SEPA
13
13
 
14
14
  validates_presence_of :transactions
15
15
  validate do |record|
16
- record.errors.add(:account, 'is invalid') unless record.account.valid?
16
+ record.errors.add(:account, record.account.errors.full_messages) unless record.account.valid?
17
17
  end
18
18
 
19
19
  class_attribute :account_class, :transaction_class, :xml_main_tag, :known_schemas
@@ -59,6 +59,13 @@ module SEPA
59
59
  end
60
60
  end
61
61
 
62
+ attr_writer :message_identification # Set unique identifer for the message
63
+
64
+ # Unique identifer for the whole message
65
+ def message_identification
66
+ @message_identification ||= "SEPA-KING/#{Time.now.to_i}"
67
+ end
68
+
62
69
  private
63
70
  # @return {Hash<Symbol=>String>} xml schema information used in output xml
64
71
  def xml_schema(schema_name)
@@ -79,11 +86,6 @@ module SEPA
79
86
  end
80
87
  end
81
88
 
82
- # Unique identifer for the whole message
83
- def message_identification
84
- @message_identification ||= "SEPA-KING/#{Time.now.to_i}"
85
- end
86
-
87
89
  # Unique and consecutive identifier (used for the <PmntInf> blocks)
88
90
  def payment_information_identification
89
91
  @payment_information_counter ||= 0
@@ -5,6 +5,12 @@ module SEPA
5
5
 
6
6
  validates_inclusion_of :service_level, :in => %w(SEPA URGP)
7
7
 
8
+ validate do |t|
9
+ if t.requested_date.is_a?(Date)
10
+ errors.add(:requested_date, 'is in the past') if t.requested_date < Date.today
11
+ end
12
+ end
13
+
8
14
  def initialize(attributes = {})
9
15
  super
10
16
  self.service_level ||= 'SEPA'
@@ -1,12 +1,15 @@
1
1
  # encoding: utf-8
2
2
  module SEPA
3
3
  class DirectDebitTransaction < Transaction
4
+ SEQUENCE_TYPES = %w(FRST OOFF RCUR FNAL)
5
+ LOCAL_INSTRUMENTS = %w(CORE COR1 B2B)
6
+
4
7
  attr_accessor :mandate_id, :mandate_date_of_signature, :local_instrument, :sequence_type, :creditor_account
5
8
 
6
- validates_length_of :mandate_id, within: 1..35
9
+ validates_with MandateIdentifierValidator, field_name: :mandate_id
7
10
  validates_presence_of :mandate_date_of_signature
8
- validates_inclusion_of :local_instrument, :in => %w(CORE COR1 B2B)
9
- validates_inclusion_of :sequence_type, :in => %w(FRST OOFF RCUR FNAL)
11
+ validates_inclusion_of :local_instrument, in: LOCAL_INSTRUMENTS
12
+ validates_inclusion_of :sequence_type, in: SEQUENCE_TYPES
10
13
 
11
14
  validate do |t|
12
15
  if creditor_account
@@ -18,6 +21,10 @@ module SEPA
18
21
  else
19
22
  errors.add(:mandate_date_of_signature, 'is not a Date')
20
23
  end
24
+
25
+ if t.requested_date.is_a?(Date)
26
+ errors.add(:requested_date, 'is not in the future') if t.requested_date <= Date.today
27
+ end
21
28
  end
22
29
 
23
30
  def initialize(attributes = {})
@@ -16,12 +16,6 @@ module SEPA
16
16
  validates_inclusion_of :batch_booking, :in => [true, false]
17
17
  validates_with BICValidator, IBANValidator
18
18
 
19
- validate do |t|
20
- if t.requested_date.is_a?(Date)
21
- errors.add(:requested_date, 'is not in the future') if t.requested_date <= Date.today
22
- end
23
- end
24
-
25
19
  def initialize(attributes = {})
26
20
  attributes.each do |name, value|
27
21
  send("#{name}=", value)
@@ -2,31 +2,44 @@
2
2
  module SEPA
3
3
  class IBANValidator < ActiveModel::Validator
4
4
  def validate(record)
5
- unless IBANTools::IBAN.valid?(record.iban.to_s)
6
- record.errors.add(:iban, :invalid)
5
+ field_name = options[:field_name] || :iban
6
+ value = record.send(field_name)
7
+
8
+ unless IBANTools::IBAN.valid?(value.to_s)
9
+ record.errors.add(field_name, :invalid)
7
10
  end
8
11
  end
9
12
  end
10
13
 
11
14
  class BICValidator < ActiveModel::Validator
15
+ REGEX = /\A[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}\z/
16
+
12
17
  def validate(record)
13
- if record.bic
14
- unless record.bic.to_s.match /[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}/
15
- record.errors.add(:bic, :invalid)
18
+ field_name = options[:field_name] || :bic
19
+ value = record.send(field_name)
20
+
21
+ if value
22
+ unless value.to_s.match(REGEX)
23
+ record.errors.add(field_name, :invalid)
16
24
  end
17
25
  end
18
26
  end
19
27
  end
20
28
 
21
29
  class CreditorIdentifierValidator < ActiveModel::Validator
30
+ REGEX = /\A[a-zA-Z]{2,2}[0-9]{2,2}([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|,|']){3,3}([A-Za-z0-9]|[\+|\?|\/|\-|:|\(|\)|\.|,|']){1,28}\z/
31
+
22
32
  def validate(record)
23
- unless valid?(record.creditor_identifier)
24
- record.errors.add(:creditor_identifier, :invalid)
33
+ field_name = options[:field_name] || :creditor_identifier
34
+ value = record.send(field_name)
35
+
36
+ unless valid?(value)
37
+ record.errors.add(field_name, :invalid)
25
38
  end
26
39
  end
27
40
 
28
41
  def valid?(creditor_identifier)
29
- if ok = creditor_identifier.to_s.match(/[a-zA-Z]{2,2}[0-9]{2,2}([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|,|']){3,3}([A-Za-z0-9]|[\+|\?|\/|\-|:|\(|\)|\.|,|']){1,28}/)
42
+ if ok = creditor_identifier.to_s.match(REGEX)
30
43
  # In Germany, the identifier has to be exactly 18 chars long
31
44
  if creditor_identifier[0..1].match(/DE/i)
32
45
  ok = creditor_identifier.length == 18
@@ -35,4 +48,17 @@ module SEPA
35
48
  ok
36
49
  end
37
50
  end
51
+
52
+ class MandateIdentifierValidator < ActiveModel::Validator
53
+ REGEX = /\A([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|\,|\']){1,35}\z/
54
+
55
+ def validate(record)
56
+ field_name = options[:field_name] || :mandate_id
57
+ value = record.send(field_name)
58
+
59
+ unless value.to_s.match(REGEX)
60
+ record.errors.add(field_name, :invalid)
61
+ end
62
+ end
63
+ end
38
64
  end
@@ -1,3 +1,3 @@
1
1
  module SEPA
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -33,4 +33,14 @@ describe SEPA::CreditTransferTransaction do
33
33
  end
34
34
  end
35
35
  end
36
+
37
+ context 'Requested date' do
38
+ it 'should allow valid value' do
39
+ SEPA::CreditTransferTransaction.should accept(nil, Date.today, Date.today.next, Date.today + 2, for: :requested_date)
40
+ end
41
+
42
+ it 'should not allow invalid value' do
43
+ SEPA::CreditTransferTransaction.should_not accept(Date.new(1995,12,21), Date.today - 1, for: :requested_date)
44
+ end
45
+ end
36
46
  end
@@ -46,13 +46,13 @@ describe SEPA::DirectDebitTransaction do
46
46
  end
47
47
  end
48
48
 
49
- context 'Mandate ID' do
49
+ context 'Requested date' do
50
50
  it 'should allow valid value' do
51
- SEPA::DirectDebitTransaction.should accept('XYZ-123', 'X' * 35, for: :mandate_id)
51
+ SEPA::DirectDebitTransaction.should accept(nil, Date.today.next, Date.today + 2, for: :requested_date)
52
52
  end
53
53
 
54
54
  it 'should not allow invalid value' do
55
- SEPA::DirectDebitTransaction.should_not accept(nil, '', 'X' * 36, for: :mandate_id)
55
+ SEPA::DirectDebitTransaction.should_not accept(Date.new(1995,12,21), Date.today - 1, Date.today, for: :requested_date)
56
56
  end
57
57
  end
58
58
  end
data/spec/message_spec.rb CHANGED
@@ -33,7 +33,7 @@ describe SEPA::Message do
33
33
 
34
34
  it 'should fail with invalid account' do
35
35
  subject.should_not be_valid
36
- subject.should have(1).error_on(:account)
36
+ subject.should have(2).error_on(:account)
37
37
  end
38
38
 
39
39
  it 'should fail without transactions' do
@@ -41,4 +41,17 @@ describe SEPA::Message do
41
41
  subject.should have(1).error_on(:transactions)
42
42
  end
43
43
  end
44
+
45
+ describe :message_identification do
46
+ subject { DummyMessage.new }
47
+
48
+ it 'should have a reader method' do
49
+ subject.message_identification.should match(/SEPA-KING\/[0-9]+/)
50
+ end
51
+
52
+ it 'should have a writer method' do
53
+ subject.message_identification = "MY_MESSAGE_ID/#{Time.now.to_i}"
54
+ subject.message_identification.should match(/MY_MESSAGE_ID/)
55
+ end
56
+ end
44
57
  end
data/spec/spec_helper.rb CHANGED
@@ -16,6 +16,10 @@ end
16
16
 
17
17
  require 'sepa_king'
18
18
 
19
+ if I18n.respond_to?(:enforce_available_locales=)
20
+ I18n.enforce_available_locales = false
21
+ end
22
+
19
23
  # Requires supporting ruby files with custom matchers and macros, etc,
20
24
  # in spec/support/ and its subdirectories.
21
25
  Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
@@ -36,21 +36,25 @@ RSpec::Matchers.define :have_xml do |xpath, text|
36
36
  end
37
37
 
38
38
  RSpec::Matchers.define :accept do |*values, options|
39
- attribute = options[:for]
40
-
41
- match_for_should do |actual|
42
- values.all? { |value|
43
- expect(
44
- actual.new(attribute => value)
45
- ).to have(:no).errors_on(attribute)
46
- }
39
+ attributes = Array(options[:for])
40
+
41
+ attributes.each do |attribute|
42
+ match_for_should do |actual|
43
+ values.all? { |value|
44
+ expect(
45
+ actual.new(attribute => value)
46
+ ).to have(:no).errors_on(attribute)
47
+ }
48
+ end
47
49
  end
48
50
 
49
- match_for_should_not do |actual|
50
- values.all? { |value|
51
- expect(
52
- actual.new(attribute => value)
53
- ).to have_at_least(1).errors_on(attribute)
54
- }
51
+ attributes.each do |attribute|
52
+ match_for_should_not do |actual|
53
+ values.all? { |value|
54
+ expect(
55
+ actual.new(attribute => value)
56
+ ).to have_at_least(1).errors_on(attribute)
57
+ }
58
+ end
55
59
  end
56
60
  end
@@ -75,14 +75,4 @@ describe SEPA::Transaction do
75
75
  SEPA::Transaction.should_not accept('', 'X' * 141, for: :remittance_information)
76
76
  end
77
77
  end
78
-
79
- context 'Requested date' do
80
- it 'should allow valid value' do
81
- SEPA::Transaction.should accept(nil, Date.today.next, Date.today + 2, for: :requested_date)
82
- end
83
-
84
- it 'should not allow invalid value' do
85
- SEPA::Transaction.should_not accept(Date.new(1995,12,21), Date.today - 1, Date.today, for: :requested_date)
86
- end
87
- end
88
78
  end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe SEPA::IBANValidator do
5
+ class Validatable
6
+ include ActiveModel::Model
7
+ attr_accessor :iban, :iban_the_terrible
8
+ validates_with SEPA::IBANValidator
9
+ validates_with SEPA::IBANValidator, field_name: :iban_the_terrible
10
+ end
11
+
12
+ it 'should accept valid IBAN' do
13
+ Validatable.should accept('DE21500500009876543210', 'DE87200500001234567890', for: [:iban, :iban_the_terrible])
14
+ end
15
+
16
+ it 'should not accept an invalid IBAN' do
17
+ Validatable.should_not accept('', 'xxx', 'DE22500500009876543210', 'DE2150050000987654321', for: [:iban, :iban_the_terrible])
18
+ end
19
+ end
20
+
21
+ describe SEPA::BICValidator do
22
+ class Validatable
23
+ include ActiveModel::Model
24
+ attr_accessor :bic, :custom_bic
25
+ validates_with SEPA::BICValidator
26
+ validates_with SEPA::BICValidator, field_name: :custom_bic
27
+ end
28
+
29
+ it 'should accept valid BICs' do
30
+ Validatable.should accept('DEUTDEDBDUE', 'DUSSDEDDXXX', for: [:bic, :custom_bic])
31
+ end
32
+
33
+ it 'should not accept an invalid BIC' do
34
+ Validatable.should_not accept('', 'GENODE61HR', 'DEUTDEDBDUEDEUTDEDBDUE', for: [:bic, :custom_bic])
35
+ end
36
+ end
37
+
38
+ describe SEPA::CreditorIdentifierValidator do
39
+ class Validatable
40
+ include ActiveModel::Model
41
+ attr_accessor :creditor_identifier, :crid
42
+ validates_with SEPA::CreditorIdentifierValidator
43
+ validates_with SEPA::CreditorIdentifierValidator, field_name: :crid
44
+ end
45
+
46
+ it 'should accept valid creditor_identifier' do
47
+ Validatable.should accept('DE98ZZZ09999999999', 'AT12ZZZ00000000001', 'FR12ZZZ123456', 'NL97ZZZ123456780001', for: [:creditor_identifier, :crid])
48
+ end
49
+
50
+ it 'should not accept an invalid creditor_identifier' do
51
+ Validatable.should_not accept('', 'xxx', 'DE98ZZZ099999999990', for: [:creditor_identifier, :crid])
52
+ end
53
+ end
54
+
55
+ describe SEPA::MandateIdentifierValidator do
56
+ class Validatable
57
+ include ActiveModel::Model
58
+ attr_accessor :mandate_id, :mid
59
+ validates_with SEPA::MandateIdentifierValidator
60
+ validates_with SEPA::MandateIdentifierValidator, field_name: :mid
61
+ end
62
+
63
+ it 'should accept valid mandate_identifier' do
64
+ Validatable.should accept('XYZ-123', "+?/-:().,'", 'X' * 35, for: [:mandate_id, :mid])
65
+ end
66
+
67
+ it 'should not accept an invalid mandate_identifier' do
68
+ Validatable.should_not accept(nil, '', 'X' * 36, 'ABC 123', '#/*', 'Ümläüt', for: [:mandate_id, :mid])
69
+ end
70
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sepa_king
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Georg Leciejewski
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-04 00:00:00.000000000 Z
12
+ date: 2014-02-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -204,6 +204,7 @@ files:
204
204
  - spec/support/validations.rb
205
205
  - spec/transaction_spec.rb
206
206
  - spec/validation_spec.rb
207
+ - spec/validator_spec.rb
207
208
  homepage: http://github.com/salesking/sepa_king
208
209
  licenses:
209
210
  - MIT
@@ -224,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
225
  version: '0'
225
226
  requirements: []
226
227
  rubyforge_project:
227
- rubygems_version: 2.1.10
228
+ rubygems_version: 2.2.2
228
229
  signing_key:
229
230
  specification_version: 4
230
231
  summary: Ruby gem for creating SEPA XML files
@@ -248,3 +249,4 @@ test_files:
248
249
  - spec/support/validations.rb
249
250
  - spec/transaction_spec.rb
250
251
  - spec/validation_spec.rb
252
+ - spec/validator_spec.rb