sepa_king 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +38 -0
- data/{MIT-LICENSE → LICENSE.txt} +2 -2
- data/README.md +174 -0
- data/Rakefile +1 -1
- data/lib/sepa_king.rb +1 -0
- data/lib/sepa_king/account.rb +8 -7
- data/lib/sepa_king/account/creditor_account.rb +2 -2
- data/lib/sepa_king/message.rb +14 -4
- data/lib/sepa_king/message/credit_transfer.rb +67 -60
- data/lib/sepa_king/message/direct_debit.rb +83 -73
- data/lib/sepa_king/transaction.rb +24 -11
- data/lib/sepa_king/transaction/direct_debit_transaction.rb +10 -2
- data/lib/sepa_king/validator.rb +36 -0
- data/lib/sepa_king/version.rb +1 -1
- data/sepa_king.gemspec +6 -4
- data/spec/account_spec.rb +8 -32
- data/spec/credit_transfer_spec.rb +170 -37
- data/spec/credit_transfer_transaction_spec.rb +6 -6
- data/spec/creditor_account_spec.rb +7 -15
- data/spec/debtor_account_spec.rb +3 -3
- data/spec/direct_debit_spec.rb +258 -43
- data/spec/direct_debit_transaction_spec.rb +14 -30
- data/spec/message_spec.rb +10 -3
- data/spec/spec_helper.rb +8 -3
- data/spec/support/custom_matcher.rb +46 -3
- data/spec/support/factories.rb +23 -0
- data/spec/support/validations.rb +1 -1
- data/spec/transaction_spec.rb +36 -60
- data/spec/validation_spec.rb +10 -2
- metadata +15 -11
- data/README.markdown +0 -91
@@ -4,98 +4,108 @@ module SEPA
|
|
4
4
|
class DirectDebit < Message
|
5
5
|
self.account_class = CreditorAccount
|
6
6
|
self.transaction_class = DirectDebitTransaction
|
7
|
+
self.xml_main_tag = 'CstmrDrctDbtInitn'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
9
|
+
private
|
10
|
+
# @return {Hash<Symbol=>String>} xml schema information used in output xml
|
11
|
+
def xml_schema
|
12
|
+
{ :xmlns => 'urn:iso:std:iso:20022:tech:xsd:pain.008.002.02',
|
13
|
+
:'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
14
|
+
:'xsi:schemaLocation' => 'urn:iso:std:iso:20022:tech:xsd:pain.008.002.02 pain.008.002.02.xsd' }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Find groups of transactions which share the same values of some attributes
|
18
|
+
def grouped_transactions
|
19
|
+
transactions.group_by do |transaction|
|
20
|
+
{ requested_date: transaction.requested_date,
|
21
|
+
local_instrument: transaction.local_instrument,
|
22
|
+
sequence_type: transaction.sequence_type,
|
23
|
+
batch_booking: transaction.batch_booking
|
24
|
+
}
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
builder.
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
builder.
|
31
|
-
|
28
|
+
def build_payment_informations(builder)
|
29
|
+
# Build a PmtInf block for every group of transactions
|
30
|
+
grouped_transactions.each do |group, transactions|
|
31
|
+
builder.PmtInf do
|
32
|
+
builder.PmtInfId(payment_information_identification)
|
33
|
+
builder.PmtMtd('DD')
|
34
|
+
builder.BtchBookg(group[:batch_booking])
|
35
|
+
builder.NbOfTxs(transactions.length)
|
36
|
+
builder.CtrlSum('%.2f' % amount_total(transactions))
|
37
|
+
builder.PmtTpInf do
|
38
|
+
builder.SvcLvl do
|
39
|
+
builder.Cd('SEPA')
|
40
|
+
end
|
41
|
+
builder.LclInstrm do
|
42
|
+
builder.Cd(group[:local_instrument])
|
43
|
+
end
|
44
|
+
builder.SeqTp(group[:sequence_type])
|
32
45
|
end
|
33
|
-
builder.
|
34
|
-
|
46
|
+
builder.ReqdColltnDt(group[:requested_date].iso8601)
|
47
|
+
builder.Cdtr do
|
48
|
+
builder.Nm(account.name)
|
35
49
|
end
|
36
|
-
builder.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
builder.Nm(account.name)
|
41
|
-
end
|
42
|
-
builder.CdtrAcct do
|
43
|
-
builder.Id do
|
44
|
-
builder.IBAN(account.iban)
|
50
|
+
builder.CdtrAcct do
|
51
|
+
builder.Id do
|
52
|
+
builder.IBAN(account.iban)
|
53
|
+
end
|
45
54
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
builder.CdtrAgt do
|
56
|
+
builder.FinInstnId do
|
57
|
+
builder.BIC(account.bic)
|
58
|
+
end
|
50
59
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
builder.ChrgBr('SLEV')
|
61
|
+
builder.CdtrSchmeId do
|
62
|
+
builder.Id do
|
63
|
+
builder.PrvtId do
|
64
|
+
builder.Othr do
|
65
|
+
builder.Id(account.creditor_identifier)
|
66
|
+
builder.SchmeNm do
|
67
|
+
builder.Prtry('SEPA')
|
68
|
+
end
|
60
69
|
end
|
61
70
|
end
|
62
71
|
end
|
63
72
|
end
|
73
|
+
|
74
|
+
transactions.each do |transaction|
|
75
|
+
build_transaction(builder, transaction)
|
76
|
+
end
|
64
77
|
end
|
65
|
-
build_transactions(builder)
|
66
78
|
end
|
67
79
|
end
|
68
80
|
|
69
|
-
def
|
70
|
-
|
71
|
-
builder.
|
72
|
-
builder.
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
builder.
|
77
|
-
builder.
|
78
|
-
|
79
|
-
builder.DtOfSgntr(transaction.mandate_date_of_signature.iso8601)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
builder.DbtrAgt do
|
83
|
-
builder.FinInstnId do
|
84
|
-
builder.BIC(transaction.bic)
|
85
|
-
end
|
81
|
+
def build_transaction(builder, transaction)
|
82
|
+
builder.DrctDbtTxInf do
|
83
|
+
builder.PmtId do
|
84
|
+
builder.EndToEndId(transaction.reference)
|
85
|
+
end
|
86
|
+
builder.InstdAmt('%.2f' % transaction.amount, Ccy: 'EUR')
|
87
|
+
builder.DrctDbtTx do
|
88
|
+
builder.MndtRltdInf do
|
89
|
+
builder.MndtId(transaction.mandate_id)
|
90
|
+
builder.DtOfSgntr(transaction.mandate_date_of_signature.iso8601)
|
86
91
|
end
|
87
|
-
|
88
|
-
|
92
|
+
end
|
93
|
+
builder.DbtrAgt do
|
94
|
+
builder.FinInstnId do
|
95
|
+
builder.BIC(transaction.bic)
|
89
96
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
97
|
+
end
|
98
|
+
builder.Dbtr do
|
99
|
+
builder.Nm(transaction.name)
|
100
|
+
end
|
101
|
+
builder.DbtrAcct do
|
102
|
+
builder.Id do
|
103
|
+
builder.IBAN(transaction.iban)
|
94
104
|
end
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
105
|
+
end
|
106
|
+
if transaction.remittance_information
|
107
|
+
builder.RmtInf do
|
108
|
+
builder.Ustrd(transaction.remittance_information)
|
99
109
|
end
|
100
110
|
end
|
101
111
|
end
|
@@ -1,22 +1,35 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module SEPA
|
3
3
|
class Transaction
|
4
|
-
include ActiveModel::
|
4
|
+
include ActiveModel::Validations
|
5
5
|
extend Converter
|
6
6
|
|
7
|
-
attr_accessor :name, :iban, :bic, :amount, :reference, :remittance_information
|
8
|
-
convert :name, :reference, :remittance_information, :
|
9
|
-
convert :amount, :
|
7
|
+
attr_accessor :name, :iban, :bic, :amount, :reference, :remittance_information, :requested_date, :batch_booking
|
8
|
+
convert :name, :reference, :remittance_information, to: :text
|
9
|
+
convert :amount, to: :decimal
|
10
10
|
|
11
|
-
|
12
|
-
validates_length_of :
|
13
|
-
validates_length_of :
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
validates_length_of :name, within: 1..70
|
12
|
+
validates_length_of :reference, within: 1..35, allow_nil: true
|
13
|
+
validates_length_of :remittance_information, within: 1..140, allow_nil: true
|
14
|
+
validates_numericality_of :amount, greater_than: 0
|
15
|
+
validates_presence_of :requested_date
|
16
|
+
validates_inclusion_of :batch_booking, :in => [true, false]
|
17
|
+
validates_with BICValidator, IBANValidator
|
17
18
|
|
18
19
|
validate do |t|
|
19
|
-
|
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
|
+
def initialize(attributes = {})
|
26
|
+
attributes.each do |name, value|
|
27
|
+
send("#{name}=", value)
|
28
|
+
end
|
29
|
+
|
30
|
+
self.requested_date ||= Date.today.next
|
31
|
+
self.reference ||= 'NOTPROVIDED'
|
32
|
+
self.batch_booking = true if self.batch_booking.nil?
|
20
33
|
end
|
21
34
|
end
|
22
35
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module SEPA
|
3
3
|
class DirectDebitTransaction < Transaction
|
4
|
-
attr_accessor :mandate_id, :mandate_date_of_signature
|
4
|
+
attr_accessor :mandate_id, :mandate_date_of_signature, :local_instrument, :sequence_type
|
5
5
|
|
6
|
-
validates_length_of :mandate_id, :
|
6
|
+
validates_length_of :mandate_id, within: 1..35
|
7
7
|
validates_presence_of :mandate_date_of_signature
|
8
|
+
validates_inclusion_of :local_instrument, :in => %w(CORE B2B)
|
9
|
+
validates_inclusion_of :sequence_type, :in => %w(FRST OOFF RCUR FNAL)
|
8
10
|
|
9
11
|
validate do |t|
|
10
12
|
if t.mandate_date_of_signature.is_a?(Date)
|
@@ -13,5 +15,11 @@ module SEPA
|
|
13
15
|
errors.add(:mandate_date_of_signature, 'is not a Date')
|
14
16
|
end
|
15
17
|
end
|
18
|
+
|
19
|
+
def initialize(attributes = {})
|
20
|
+
super
|
21
|
+
self.local_instrument ||= 'CORE'
|
22
|
+
self.sequence_type ||= 'OOFF'
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SEPA
|
3
|
+
class IBANValidator < ActiveModel::Validator
|
4
|
+
def validate(record)
|
5
|
+
unless IBANTools::IBAN.valid?(record.iban.to_s)
|
6
|
+
record.errors.add(:iban, 'is invalid')
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class BICValidator < ActiveModel::Validator
|
12
|
+
def validate(record)
|
13
|
+
unless record.bic.to_s.match /[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}/
|
14
|
+
record.errors.add(:bic, 'is invalid')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class CreditorIdentifierValidator < ActiveModel::Validator
|
20
|
+
def validate(record)
|
21
|
+
unless valid?(record.creditor_identifier)
|
22
|
+
record.errors.add(:creditor_identifier, 'is invalid')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid?(creditor_identifier)
|
27
|
+
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}/)
|
28
|
+
# In Germany, the identifier has to be exactly 18 chars long
|
29
|
+
if creditor_identifier[0..1].match(/DE/i)
|
30
|
+
ok = creditor_identifier.length == 18
|
31
|
+
end
|
32
|
+
end
|
33
|
+
ok
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/sepa_king/version.rb
CHANGED
data/sepa_king.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ['Georg Leciejewski', 'Georg Ledermann']
|
10
10
|
s.email = ['gl@salesking.eu', 'mail@georg-ledermann.de']
|
11
11
|
s.description = 'Implemention of pain.001.002.03 and pain.008.002.02 (ISO 20022)'
|
12
|
-
s.summary = '
|
12
|
+
s.summary = 'Ruby gem for creating SEPA XML files'
|
13
13
|
s.homepage = 'http://github.com/salesking/sepa_king'
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
@@ -18,15 +18,17 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
|
+
s.required_ruby_version = '>= 1.9.3'
|
22
|
+
|
21
23
|
s.add_runtime_dependency 'activemodel'
|
22
24
|
s.add_runtime_dependency 'i18n'
|
23
25
|
s.add_runtime_dependency 'builder'
|
24
26
|
s.add_runtime_dependency 'iban-tools'
|
25
27
|
|
26
28
|
s.add_development_dependency 'bundler', '~> 1.3'
|
27
|
-
s.add_development_dependency 'rspec'
|
28
|
-
s.add_development_dependency 'simplecov'
|
29
|
+
s.add_development_dependency 'rspec', '>=2.14'
|
29
30
|
s.add_development_dependency 'coveralls'
|
31
|
+
s.add_development_dependency 'simplecov'
|
30
32
|
s.add_development_dependency 'rake'
|
31
|
-
s.add_development_dependency '
|
33
|
+
s.add_development_dependency 'nokogiri'
|
32
34
|
end
|
data/spec/account_spec.rb
CHANGED
@@ -2,65 +2,41 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe SEPA::Account do
|
5
|
-
describe
|
5
|
+
describe :new do
|
6
6
|
it 'should not accept unknown keys' do
|
7
7
|
expect {
|
8
|
-
SEPA::Account.new :
|
8
|
+
SEPA::Account.new foo: 'bar'
|
9
9
|
}.to raise_error(NoMethodError)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
describe :name do
|
14
14
|
it 'should accept valid value' do
|
15
|
-
|
16
|
-
expect(
|
17
|
-
SEPA::Account.new :name => value_value
|
18
|
-
).to have(:no).errors_on(:name)
|
19
|
-
end
|
15
|
+
SEPA::Account.should accept('Gläubiger GmbH', 'Zahlemann & Söhne GbR', 'X' * 70, for: :name)
|
20
16
|
end
|
21
17
|
|
22
18
|
it 'should not accept invalid value' do
|
23
|
-
|
24
|
-
expect(
|
25
|
-
SEPA::Account.new :name => invalue_value
|
26
|
-
).to have_at_least(1).errors_on(:name)
|
27
|
-
end
|
19
|
+
SEPA::Account.should_not accept(nil, '', 'X' * 71, for: :name)
|
28
20
|
end
|
29
21
|
end
|
30
22
|
|
31
23
|
describe :iban do
|
32
24
|
it 'should accept valid value' do
|
33
|
-
|
34
|
-
expect(
|
35
|
-
SEPA::Account.new :iban => value_value
|
36
|
-
).to have(:no).errors_on(:iban)
|
37
|
-
end
|
25
|
+
SEPA::Account.should accept('DE21500500009876543210', 'PL61109010140000071219812874', for: :iban)
|
38
26
|
end
|
39
27
|
|
40
28
|
it 'should not accept invalid value' do
|
41
|
-
|
42
|
-
expect(
|
43
|
-
SEPA::Account.new :iban => invalue_value
|
44
|
-
).to have_at_least(1).errors_on(:iban)
|
45
|
-
end
|
29
|
+
SEPA::Account.should_not accept(nil, '', 'invalid', for: :iban)
|
46
30
|
end
|
47
31
|
end
|
48
32
|
|
49
33
|
describe :bic do
|
50
34
|
it 'should accept valid value' do
|
51
|
-
|
52
|
-
expect(
|
53
|
-
SEPA::Account.new :bic => value_value
|
54
|
-
).to have(:no).errors_on(:bic)
|
55
|
-
end
|
35
|
+
SEPA::Account.should accept('DEUTDEFF', 'DEUTDEFF500', 'SPUEDE2UXXX', for: :bic)
|
56
36
|
end
|
57
37
|
|
58
38
|
it 'should not accept invalid value' do
|
59
|
-
|
60
|
-
expect(
|
61
|
-
SEPA::Account.new :bic => invalue_value
|
62
|
-
).to have_at_least(1).errors_on(:bic)
|
63
|
-
end
|
39
|
+
SEPA::Account.should_not accept(nil, '', 'invalid', for: :bic)
|
64
40
|
end
|
65
41
|
end
|
66
42
|
end
|
@@ -3,13 +3,13 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
describe SEPA::CreditTransfer do
|
5
5
|
let(:credit_transfer) {
|
6
|
-
SEPA::CreditTransfer.new :
|
7
|
-
:
|
8
|
-
:
|
6
|
+
SEPA::CreditTransfer.new name: 'Schuldner GmbH',
|
7
|
+
bic: 'BANKDEFFXXX',
|
8
|
+
iban: 'DE87200500001234567890'
|
9
9
|
}
|
10
10
|
|
11
11
|
describe :new do
|
12
|
-
it 'should accept
|
12
|
+
it 'should accept missing options' do
|
13
13
|
expect {
|
14
14
|
SEPA::CreditTransfer.new
|
15
15
|
}.to_not raise_error
|
@@ -18,52 +18,185 @@ describe SEPA::CreditTransfer do
|
|
18
18
|
|
19
19
|
describe :add_transaction do
|
20
20
|
it 'should add valid transactions' do
|
21
|
-
3.times
|
22
|
-
credit_transfer.add_transaction
|
23
|
-
|
24
|
-
:iban => 'DE37112589611964645802',
|
25
|
-
:amount => 102.50,
|
26
|
-
:reference => 'XYZ-1234/123',
|
27
|
-
:remittance_information => 'Rechnung vom 22.08.2013'
|
28
|
-
}
|
21
|
+
3.times do
|
22
|
+
credit_transfer.add_transaction(credit_transfer_transaction)
|
23
|
+
end
|
29
24
|
|
30
25
|
expect(credit_transfer).to have(3).transactions
|
31
26
|
end
|
32
27
|
|
33
28
|
it 'should fail for invalid transaction' do
|
34
29
|
expect {
|
35
|
-
credit_transfer.add_transaction :
|
30
|
+
credit_transfer.add_transaction name: ''
|
36
31
|
}.to raise_error(ArgumentError)
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
40
35
|
describe :to_xml do
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
context 'for invalid debtor' do
|
37
|
+
it 'should fail' do
|
38
|
+
expect {
|
39
|
+
SEPA::CreditTransfer.new.to_xml
|
40
|
+
}.to raise_error(RuntimeError)
|
41
|
+
end
|
45
42
|
end
|
46
43
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
44
|
+
context 'for valid debtor' do
|
45
|
+
context 'without requested_date given' do
|
46
|
+
subject do
|
47
|
+
sct = credit_transfer
|
48
|
+
|
49
|
+
sct.add_transaction name: 'Telekomiker AG',
|
50
|
+
bic: 'PBNKDEFF370',
|
51
|
+
iban: 'DE37112589611964645802',
|
52
|
+
amount: 102.50,
|
53
|
+
reference: 'XYZ-1234/123',
|
54
|
+
remittance_information: 'Rechnung vom 22.08.2013'
|
55
|
+
|
56
|
+
sct.add_transaction name: 'Amazonas GmbH',
|
57
|
+
bic: 'TUBDDEDDXXX',
|
58
|
+
iban: 'DE27793589132923472195',
|
59
|
+
amount: 59.00,
|
60
|
+
reference: 'XYZ-5678/456',
|
61
|
+
remittance_information: 'Rechnung vom 21.08.2013'
|
62
|
+
|
63
|
+
sct.to_xml
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should create valid XML file' do
|
67
|
+
expect(subject).to validate_against('pain.001.002.03.xsd')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should contain <PmtMtd>' do
|
71
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/PmtMtd', 'TRF')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should contain <BtchBookg>' do
|
75
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/BtchBookg', 'true')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should contain <NbOfTxs>' do
|
79
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/NbOfTxs', '2')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should contain <CtrlSum>' do
|
83
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CtrlSum', '161.50')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should contain <Dbtr>' do
|
87
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/Dbtr/Nm', 'Schuldner GmbH')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should contain <DbtrAcct>' do
|
91
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/DbtrAcct/Id/IBAN', 'DE87200500001234567890')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should contain <DbtrAgt>' do
|
95
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/DbtrAgt/FinInstnId/BIC', 'BANKDEFFXXX')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should contain <EndToEndId>' do
|
99
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/PmtId/EndToEndId', 'XYZ-1234/123')
|
100
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/PmtId/EndToEndId', 'XYZ-5678/456')
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should contain <Amt>' do
|
104
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Amt/InstdAmt', '102.50')
|
105
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/Amt/InstdAmt', '59.00')
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should contain <CdtrAgt>' do
|
109
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/CdtrAgt/FinInstnId/BIC', 'PBNKDEFF370')
|
110
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/CdtrAgt/FinInstnId/BIC', 'TUBDDEDDXXX')
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should contain <Cdtr>' do
|
114
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Cdtr/Nm', 'Telekomiker AG')
|
115
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/Cdtr/Nm', 'Amazonas GmbH')
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should contain <CdtrAcct>' do
|
119
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/CdtrAcct/Id/IBAN', 'DE37112589611964645802')
|
120
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/CdtrAcct/Id/IBAN', 'DE27793589132923472195')
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should contain <RmtInf>' do
|
124
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/RmtInf/Ustrd', 'Rechnung vom 22.08.2013')
|
125
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/RmtInf/Ustrd', 'Rechnung vom 21.08.2013')
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with different requested_date given' do
|
130
|
+
subject do
|
131
|
+
sct = credit_transfer
|
132
|
+
|
133
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1)
|
134
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2)
|
135
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2)
|
136
|
+
|
137
|
+
sct.to_xml
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should contain two payment_informations with <ReqdExctnDt>' do
|
141
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/ReqdExctnDt', (Date.today + 1).iso8601)
|
142
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/ReqdExctnDt', (Date.today + 2).iso8601)
|
143
|
+
|
144
|
+
subject.should_not have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]')
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with different batch_booking given' do
|
149
|
+
subject do
|
150
|
+
sct = credit_transfer
|
151
|
+
|
152
|
+
sct.add_transaction(credit_transfer_transaction.merge batch_booking: false)
|
153
|
+
sct.add_transaction(credit_transfer_transaction.merge batch_booking: true)
|
154
|
+
sct.add_transaction(credit_transfer_transaction.merge batch_booking: true)
|
155
|
+
|
156
|
+
sct.to_xml
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should contain two payment_informations with <BtchBookg>' do
|
160
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/BtchBookg', 'false')
|
161
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/BtchBookg', 'true')
|
162
|
+
|
163
|
+
subject.should_not have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]')
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'with transactions containing different group criteria' do
|
168
|
+
subject do
|
169
|
+
sct = credit_transfer
|
170
|
+
|
171
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1, batch_booking: false, amount: 1)
|
172
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1, batch_booking: true, amount: 2)
|
173
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2, batch_booking: false, amount: 4)
|
174
|
+
sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2, batch_booking: true, amount: 8)
|
175
|
+
|
176
|
+
sct.to_xml
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should contain multiple payment_informations' do
|
180
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/ReqdExctnDt', (Date.today + 1).iso8601)
|
181
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/BtchBookg', 'false')
|
182
|
+
|
183
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/ReqdExctnDt', (Date.today + 1).iso8601)
|
184
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/BtchBookg', 'true')
|
185
|
+
|
186
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/ReqdExctnDt', (Date.today + 2).iso8601)
|
187
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/BtchBookg', 'false')
|
188
|
+
|
189
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/ReqdExctnDt', (Date.today + 2).iso8601)
|
190
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/BtchBookg', 'true')
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should have multiple control sums' do
|
194
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/CtrlSum', '1.00')
|
195
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/CtrlSum', '2.00')
|
196
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/CtrlSum', '4.00')
|
197
|
+
subject.should have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/CtrlSum', '8.00')
|
198
|
+
end
|
199
|
+
end
|
67
200
|
end
|
68
201
|
end
|
69
202
|
end
|