sepa_king 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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