sepa_king_codeur 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +37 -0
  5. data/CONTRIBUTING.md +38 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +297 -0
  9. data/Rakefile +6 -0
  10. data/gemfiles/Gemfile-activemodel-3.1.x +5 -0
  11. data/gemfiles/Gemfile-activemodel-3.2.x +5 -0
  12. data/gemfiles/Gemfile-activemodel-4.0.x +5 -0
  13. data/gemfiles/Gemfile-activemodel-4.1.x +5 -0
  14. data/gemfiles/Gemfile-activemodel-4.2.x +5 -0
  15. data/gemfiles/Gemfile-activemodel-5.0.x +5 -0
  16. data/gemfiles/Gemfile-activemodel-5.1.x +5 -0
  17. data/gemfiles/Gemfile-activemodel-5.2.x +5 -0
  18. data/gemfiles/Gemfile-activemodel-6.0.x +5 -0
  19. data/lib/schema/pain.001.001.03.ch.02.xsd +1212 -0
  20. data/lib/schema/pain.001.001.03.xsd +921 -0
  21. data/lib/schema/pain.001.002.03.xsd +450 -0
  22. data/lib/schema/pain.001.003.03.xsd +474 -0
  23. data/lib/schema/pain.008.001.02.xsd +879 -0
  24. data/lib/schema/pain.008.002.02.xsd +597 -0
  25. data/lib/schema/pain.008.003.02.xsd +614 -0
  26. data/lib/sepa_king.rb +19 -0
  27. data/lib/sepa_king/account.rb +19 -0
  28. data/lib/sepa_king/account/creditor_account.rb +8 -0
  29. data/lib/sepa_king/account/creditor_address.rb +37 -0
  30. data/lib/sepa_king/account/debtor_account.rb +5 -0
  31. data/lib/sepa_king/account/debtor_address.rb +37 -0
  32. data/lib/sepa_king/converter.rb +51 -0
  33. data/lib/sepa_king/error.rb +4 -0
  34. data/lib/sepa_king/message.rb +169 -0
  35. data/lib/sepa_king/message/credit_transfer.rb +137 -0
  36. data/lib/sepa_king/message/direct_debit.rb +207 -0
  37. data/lib/sepa_king/transaction.rb +56 -0
  38. data/lib/sepa_king/transaction/credit_transfer_transaction.rb +31 -0
  39. data/lib/sepa_king/transaction/direct_debit_transaction.rb +56 -0
  40. data/lib/sepa_king/validator.rb +57 -0
  41. data/lib/sepa_king/version.rb +3 -0
  42. data/sepa_king.gemspec +33 -0
  43. data/spec/account_spec.rb +42 -0
  44. data/spec/converter_spec.rb +74 -0
  45. data/spec/credit_transfer_spec.rb +520 -0
  46. data/spec/credit_transfer_transaction_spec.rb +74 -0
  47. data/spec/creditor_account_spec.rb +23 -0
  48. data/spec/debtor_account_spec.rb +12 -0
  49. data/spec/debtor_address_spec.rb +12 -0
  50. data/spec/direct_debit_spec.rb +657 -0
  51. data/spec/direct_debit_transaction_spec.rb +69 -0
  52. data/spec/examples/pain.001.001.03.ch.02.xml +172 -0
  53. data/spec/examples/pain.001.001.03.xml +89 -0
  54. data/spec/examples/pain.001.002.03.xml +89 -0
  55. data/spec/examples/pain.001.003.03.xml +89 -0
  56. data/spec/examples/pain.008.002.02.xml +134 -0
  57. data/spec/examples/pain.008.003.02.xml +134 -0
  58. data/spec/message_spec.rb +128 -0
  59. data/spec/spec_helper.rb +33 -0
  60. data/spec/support/active_model.rb +30 -0
  61. data/spec/support/custom_matcher.rb +60 -0
  62. data/spec/support/factories.rb +24 -0
  63. data/spec/support/validations.rb +27 -0
  64. data/spec/transaction_spec.rb +134 -0
  65. data/spec/validation_spec.rb +25 -0
  66. data/spec/validator_spec.rb +99 -0
  67. metadata +250 -0
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe SEPA::Account do
5
+ describe :new do
6
+ it 'should not accept unknown keys' do
7
+ expect {
8
+ SEPA::Account.new foo: 'bar'
9
+ }.to raise_error(NoMethodError)
10
+ end
11
+ end
12
+
13
+ describe :name do
14
+ it 'should accept valid value' do
15
+ expect(SEPA::Account).to accept('Gläubiger GmbH', 'Zahlemann & Söhne GbR', 'X' * 70, for: :name)
16
+ end
17
+
18
+ it 'should not accept invalid value' do
19
+ expect(SEPA::Account).not_to accept(nil, '', 'X' * 71, for: :name)
20
+ end
21
+ end
22
+
23
+ describe :iban do
24
+ it 'should accept valid value' do
25
+ expect(SEPA::Account).to accept('DE21500500009876543210', 'PL61109010140000071219812874', for: :iban)
26
+ end
27
+
28
+ it 'should not accept invalid value' do
29
+ expect(SEPA::Account).not_to accept(nil, '', 'invalid', for: :iban)
30
+ end
31
+ end
32
+
33
+ describe :bic do
34
+ it 'should accept valid value' do
35
+ expect(SEPA::Account).to accept('DEUTDEFF', 'DEUTDEFF500', 'SPUEDE2UXXX', for: :bic)
36
+ end
37
+
38
+ it 'should not accept invalid value' do
39
+ expect(SEPA::Account).not_to accept('', 'invalid', for: :bic)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe SEPA::Converter do
5
+ include SEPA::Converter::InstanceMethods
6
+
7
+ describe :convert_text do
8
+ it 'should convert special chars' do
9
+ expect(convert_text('10€')).to eq('10E')
10
+ expect(convert_text('info@bundesbank.de')).to eq('info(at)bundesbank.de')
11
+ expect(convert_text('abc_def')).to eq('abc-def')
12
+ end
13
+
14
+ it 'should not change allowed special character' do
15
+ expect(convert_text('üöäÜÖÄß')).to eq('üöäÜÖÄß')
16
+ expect(convert_text('&*$%')).to eq('&*$%')
17
+ end
18
+
19
+ it 'should convert line breaks' do
20
+ expect(convert_text("one\ntwo")) .to eq('one two')
21
+ expect(convert_text("one\ntwo\n")) .to eq('one two')
22
+ expect(convert_text("\none\ntwo\n")).to eq('one two')
23
+ expect(convert_text("one\n\ntwo")) .to eq('one two')
24
+ end
25
+
26
+ it 'should convert number' do
27
+ expect(convert_text(1234)).to eq('1234')
28
+ end
29
+
30
+ it 'should remove invalid chars' do
31
+ expect(convert_text('"=<>!')).to eq('')
32
+ end
33
+
34
+ it 'should not touch valid chars' do
35
+ expect(convert_text("abc-ABC-0123- ':?,-(+.)/")).to eq("abc-ABC-0123- ':?,-(+.)/")
36
+ end
37
+
38
+ it 'should not touch nil' do
39
+ expect(convert_text(nil)).to eq(nil)
40
+ end
41
+ end
42
+
43
+ describe :convert_decimal do
44
+ it "should convert Integer to BigDecimal" do
45
+ expect(convert_decimal(42)).to eq(BigDecimal('42.00'))
46
+ end
47
+
48
+ it "should convert Float to BigDecimal" do
49
+ expect(convert_decimal(42.12)).to eq(BigDecimal('42.12'))
50
+ end
51
+
52
+ it 'should round' do
53
+ expect(convert_decimal(1.345)).to eq(BigDecimal('1.35'))
54
+ end
55
+
56
+ it 'should not touch nil' do
57
+ expect(convert_decimal(nil)).to eq(nil)
58
+ end
59
+
60
+ it 'should not convert zero value' do
61
+ expect(convert_decimal(0)).to eq(nil)
62
+ end
63
+
64
+ it 'should not convert negative value' do
65
+ expect(convert_decimal(-3)).to eq(nil)
66
+ end
67
+
68
+ it 'should not convert invalid value' do
69
+ expect(convert_decimal('xyz')).to eq(nil)
70
+ expect(convert_decimal('NaN')).to eq(nil)
71
+ expect(convert_decimal('Infinity')).to eq(nil)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,520 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe SEPA::CreditTransfer do
5
+ let(:message_id_regex) { /SEPA-KING\/[0-9a-z_]{22}/ }
6
+ let(:credit_transfer) {
7
+ SEPA::CreditTransfer.new name: 'Schuldner GmbH',
8
+ bic: 'BANKDEFFXXX',
9
+ iban: 'DE87200500001234567890'
10
+ }
11
+
12
+ describe :new do
13
+ it 'should accept missing options' do
14
+ expect {
15
+ SEPA::CreditTransfer.new
16
+ }.to_not raise_error
17
+ end
18
+ end
19
+
20
+ describe :add_transaction do
21
+ it 'should add valid transactions' do
22
+ 3.times do
23
+ credit_transfer.add_transaction(credit_transfer_transaction)
24
+ end
25
+
26
+ expect(credit_transfer.transactions.size).to eq(3)
27
+ end
28
+
29
+ it 'should fail for invalid transaction' do
30
+ expect {
31
+ credit_transfer.add_transaction name: ''
32
+ }.to raise_error(ArgumentError)
33
+ end
34
+ end
35
+
36
+ describe :to_xml do
37
+ context 'for invalid debtor' do
38
+ it 'should fail' do
39
+ expect {
40
+ SEPA::CreditTransfer.new.to_xml
41
+ }.to raise_error(SEPA::Error)
42
+ end
43
+ end
44
+
45
+ context 'setting creditor address with adrline' do
46
+ subject do
47
+ sct = SEPA::CreditTransfer.new name: 'Schuldner GmbH',
48
+ iban: 'DE87200500001234567890'
49
+
50
+ sca = SEPA::CreditorAddress.new country_code: 'CH',
51
+ address_line1: 'Mustergasse 123',
52
+ address_line2: '1234 Musterstadt'
53
+
54
+ sct.add_transaction name: 'Telekomiker AG',
55
+ bic: 'PBNKDEFF370',
56
+ iban: 'DE37112589611964645802',
57
+ amount: 102.50,
58
+ reference: 'XYZ-1234/123',
59
+ remittance_information: 'Rechnung vom 22.08.2013',
60
+ creditor_address: sca
61
+
62
+ sct
63
+ end
64
+
65
+ it 'should validate against pain.001.003.01' do
66
+ expect(subject.to_xml(SEPA::PAIN_001_003_03)).to validate_against('pain.001.003.03.xsd')
67
+ end
68
+ end
69
+
70
+ context 'setting creditor address with structured fields' do
71
+ subject do
72
+ sct = SEPA::CreditTransfer.new name: 'Schuldner GmbH',
73
+ iban: 'DE87200500001234567890',
74
+ bic: 'BANKDEFFXXX'
75
+
76
+ sca = SEPA::CreditorAddress.new country_code: 'CH',
77
+ street_name: 'Mustergasse',
78
+ building_number: '123',
79
+ post_code: '1234',
80
+ town_name: 'Musterstadt'
81
+
82
+ sct.add_transaction name: 'Telekomiker AG',
83
+ bic: 'PBNKDEFF370',
84
+ iban: 'DE37112589611964645802',
85
+ amount: 102.50,
86
+ reference: 'XYZ-1234/123',
87
+ remittance_information: 'Rechnung vom 22.08.2013',
88
+ creditor_address: sca
89
+
90
+ sct
91
+ end
92
+
93
+ it 'should validate against pain.001.001.01' do
94
+ expect(subject.to_xml(SEPA::PAIN_001_001_03)).to validate_against('pain.001.001.03.xsd')
95
+ end
96
+ end
97
+
98
+ context 'for valid debtor' do
99
+ context 'without BIC (IBAN-only)' do
100
+ subject do
101
+ sct = SEPA::CreditTransfer.new name: 'Schuldner GmbH',
102
+ iban: 'DE87200500001234567890'
103
+
104
+ sct.add_transaction name: 'Telekomiker AG',
105
+ bic: 'PBNKDEFF370',
106
+ iban: 'DE37112589611964645802',
107
+ amount: 102.50,
108
+ reference: 'XYZ-1234/123',
109
+ remittance_information: 'Rechnung vom 22.08.2013'
110
+
111
+ sct
112
+ end
113
+
114
+ it 'should create valid XML file' do
115
+ expect(subject.to_xml).to validate_against('pain.001.003.03.xsd')
116
+ end
117
+
118
+ it 'should fail for pain.001.001.03' do
119
+ expect {
120
+ subject.to_xml(SEPA::PAIN_001_001_03)
121
+ }.to raise_error(SEPA::Error)
122
+ end
123
+
124
+ it 'should fail for pain.001.002.03' do
125
+ expect {
126
+ subject.to_xml(SEPA::PAIN_001_002_03)
127
+ }.to raise_error(SEPA::Error)
128
+ end
129
+ end
130
+
131
+ context 'with BIC' do
132
+ subject do
133
+ sct = credit_transfer
134
+
135
+ sct.add_transaction name: 'Telekomiker AG',
136
+ bic: 'PBNKDEFF370',
137
+ iban: 'DE37112589611964645802',
138
+ amount: 102.50,
139
+ reference: 'XYZ-1234/123',
140
+ remittance_information: 'Rechnung vom 22.08.2013'
141
+
142
+ sct
143
+ end
144
+
145
+ it 'should validate against pain.001.001.03' do
146
+ expect(subject.to_xml('pain.001.001.03')).to validate_against('pain.001.001.03.xsd')
147
+ end
148
+
149
+ it 'should validate against pain.001.002.03' do
150
+ expect(subject.to_xml('pain.001.002.03')).to validate_against('pain.001.002.03.xsd')
151
+ end
152
+
153
+ it 'should validate against pain.001.003.03' do
154
+ expect(subject.to_xml('pain.001.003.03')).to validate_against('pain.001.003.03.xsd')
155
+ end
156
+ end
157
+
158
+ context 'without requested_date given' do
159
+ subject do
160
+ sct = credit_transfer
161
+
162
+ sct.add_transaction name: 'Telekomiker AG',
163
+ bic: 'PBNKDEFF370',
164
+ iban: 'DE37112589611964645802',
165
+ amount: 102.50,
166
+ reference: 'XYZ-1234/123',
167
+ remittance_information: 'Rechnung vom 22.08.2013'
168
+
169
+ sct.add_transaction name: 'Amazonas GmbH',
170
+ iban: 'DE27793589132923472195',
171
+ amount: 59.00,
172
+ reference: 'XYZ-5678/456',
173
+ remittance_information: 'Rechnung vom 21.08.2013'
174
+
175
+ sct.to_xml
176
+ end
177
+
178
+ it 'should create valid XML file' do
179
+ expect(subject).to validate_against('pain.001.003.03.xsd')
180
+ end
181
+
182
+ it 'should have message_identification' do
183
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/GrpHdr/MsgId', message_id_regex)
184
+ end
185
+
186
+ it 'should contain <PmtInfId>' do
187
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/PmtInfId', /#{message_id_regex}\/1/)
188
+ end
189
+
190
+ it 'should contain <ReqdExctnDt>' do
191
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/ReqdExctnDt', Date.new(1999, 1, 1).iso8601)
192
+ end
193
+
194
+ it 'should contain <PmtMtd>' do
195
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/PmtMtd', 'TRF')
196
+ end
197
+
198
+ it 'should contain <BtchBookg>' do
199
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/BtchBookg', 'true')
200
+ end
201
+
202
+ it 'should contain <NbOfTxs>' do
203
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/NbOfTxs', '2')
204
+ end
205
+
206
+ it 'should contain <CtrlSum>' do
207
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CtrlSum', '161.50')
208
+ end
209
+
210
+ it 'should contain <Dbtr>' do
211
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/Dbtr/Nm', 'Schuldner GmbH')
212
+ end
213
+
214
+ it 'should contain <DbtrAcct>' do
215
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/DbtrAcct/Id/IBAN', 'DE87200500001234567890')
216
+ end
217
+
218
+ it 'should contain <DbtrAgt>' do
219
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/DbtrAgt/FinInstnId/BIC', 'BANKDEFFXXX')
220
+ end
221
+
222
+ it 'should contain <EndToEndId>' do
223
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/PmtId/EndToEndId', 'XYZ-1234/123')
224
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/PmtId/EndToEndId', 'XYZ-5678/456')
225
+ end
226
+
227
+ it 'should contain <Amt>' do
228
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Amt/InstdAmt', '102.50')
229
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/Amt/InstdAmt', '59.00')
230
+ end
231
+
232
+ it 'should contain <CdtrAgt> for every BIC given' do
233
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/CdtrAgt/FinInstnId/BIC', 'PBNKDEFF370')
234
+ expect(subject).not_to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/CdtrAgt')
235
+ end
236
+
237
+ it 'should contain <Cdtr>' do
238
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Cdtr/Nm', 'Telekomiker AG')
239
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/Cdtr/Nm', 'Amazonas GmbH')
240
+ end
241
+
242
+ it 'should contain <CdtrAcct>' do
243
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/CdtrAcct/Id/IBAN', 'DE37112589611964645802')
244
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/CdtrAcct/Id/IBAN', 'DE27793589132923472195')
245
+ end
246
+
247
+ it 'should contain <RmtInf>' do
248
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/RmtInf/Ustrd', 'Rechnung vom 22.08.2013')
249
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[2]/RmtInf/Ustrd', 'Rechnung vom 21.08.2013')
250
+ end
251
+ end
252
+
253
+ context 'with different requested_date given' do
254
+ subject do
255
+ sct = credit_transfer
256
+
257
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1)
258
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2)
259
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2)
260
+
261
+ sct.to_xml
262
+ end
263
+
264
+ it 'should contain two payment_informations with <ReqdExctnDt>' do
265
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/ReqdExctnDt', (Date.today + 1).iso8601)
266
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/ReqdExctnDt', (Date.today + 2).iso8601)
267
+
268
+ expect(subject).not_to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]')
269
+ end
270
+
271
+ it 'should contain two payment_informations with different <PmtInfId>' do
272
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/PmtInfId', /#{message_id_regex}\/1/)
273
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/PmtInfId', /#{message_id_regex}\/2/)
274
+ end
275
+ end
276
+
277
+ context 'with different batch_booking given' do
278
+ subject do
279
+ sct = credit_transfer
280
+
281
+ sct.add_transaction(credit_transfer_transaction.merge batch_booking: false)
282
+ sct.add_transaction(credit_transfer_transaction.merge batch_booking: true)
283
+ sct.add_transaction(credit_transfer_transaction.merge batch_booking: true)
284
+
285
+ sct.to_xml
286
+ end
287
+
288
+ it 'should contain two payment_informations with <BtchBookg>' do
289
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/BtchBookg', 'false')
290
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/BtchBookg', 'true')
291
+
292
+ expect(subject).not_to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]')
293
+ end
294
+ end
295
+
296
+ context 'with transactions containing different group criteria' do
297
+ subject do
298
+ sct = credit_transfer
299
+
300
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1, batch_booking: false, amount: 1)
301
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 1, batch_booking: true, amount: 2)
302
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2, batch_booking: false, amount: 4)
303
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2, batch_booking: true, amount: 8)
304
+ sct.add_transaction(credit_transfer_transaction.merge requested_date: Date.today + 2, batch_booking: true, category_purpose: 'SALA', amount: 6)
305
+
306
+ sct.to_xml
307
+ end
308
+
309
+ it 'should contain multiple payment_informations' do
310
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/ReqdExctnDt', (Date.today + 1).iso8601)
311
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/BtchBookg', 'false')
312
+
313
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/ReqdExctnDt', (Date.today + 1).iso8601)
314
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/BtchBookg', 'true')
315
+
316
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/ReqdExctnDt', (Date.today + 2).iso8601)
317
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/BtchBookg', 'false')
318
+
319
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/ReqdExctnDt', (Date.today + 2).iso8601)
320
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/BtchBookg', 'true')
321
+
322
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[5]/ReqdExctnDt', (Date.today + 2).iso8601)
323
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[5]/PmtTpInf/CtgyPurp/Cd', 'SALA')
324
+ end
325
+
326
+ it 'should have multiple control sums' do
327
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/CtrlSum', '1.00')
328
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/CtrlSum', '2.00')
329
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[3]/CtrlSum', '4.00')
330
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[4]/CtrlSum', '8.00')
331
+ end
332
+ end
333
+
334
+ context 'with instruction given' do
335
+ subject do
336
+ sct = credit_transfer
337
+
338
+ sct.add_transaction name: 'Telekomiker AG',
339
+ iban: 'DE37112589611964645802',
340
+ amount: 102.50,
341
+ instruction: '1234/ABC'
342
+
343
+ sct.to_xml
344
+ end
345
+
346
+ it 'should create valid XML file' do
347
+ expect(subject).to validate_against('pain.001.003.03.xsd')
348
+ end
349
+
350
+ it 'should contain <InstrId>' do
351
+ expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/PmtId/InstrId', '1234/ABC')
352
+ end
353
+ end
354
+
355
+ context 'with a different currency given' do
356
+ subject do
357
+ sct = credit_transfer
358
+
359
+ sct.add_transaction name: 'Telekomiker AG',
360
+ iban: 'DE37112589611964645802',
361
+ bic: 'PBNKDEFF370',
362
+ amount: 102.50,
363
+ currency: 'CHF'
364
+
365
+ sct
366
+ end
367
+
368
+ it 'should validate against pain.001.001.03' do
369
+ expect(subject.to_xml('pain.001.001.03')).to validate_against('pain.001.001.03.xsd')
370
+ end
371
+
372
+ it 'should have a CHF Ccy' do
373
+ doc = Nokogiri::XML(subject.to_xml('pain.001.001.03'))
374
+ doc.remove_namespaces!
375
+
376
+ nodes = doc.xpath('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Amt/InstdAmt')
377
+ expect(nodes.length).to eql(1)
378
+ expect(nodes.first.attribute('Ccy').value).to eql('CHF')
379
+ end
380
+
381
+ it 'should fail for pain.001.002.03' do
382
+ expect {
383
+ subject.to_xml(SEPA::PAIN_001_002_03)
384
+ }.to raise_error(SEPA::Error)
385
+ end
386
+
387
+ it 'should fail for pain.001.003.03' do
388
+ expect {
389
+ subject.to_xml(SEPA::PAIN_001_003_03)
390
+ }.to raise_error(SEPA::Error)
391
+ end
392
+ end
393
+
394
+ context 'with a transaction without a bic' do
395
+ subject do
396
+ sct = credit_transfer
397
+
398
+ sct.add_transaction name: 'Telekomiker AG',
399
+ iban: 'DE37112589611964645802',
400
+ amount: 102.50
401
+
402
+ sct
403
+ end
404
+
405
+ it 'should validate against pain.001.001.03' do
406
+ expect(subject.to_xml('pain.001.001.03')).to validate_against('pain.001.001.03.xsd')
407
+ end
408
+
409
+ it 'should fail for pain.001.002.03' do
410
+ expect {
411
+ subject.to_xml(SEPA::PAIN_001_002_03)
412
+ }.to raise_error(SEPA::Error)
413
+ end
414
+
415
+ it 'should validate against pain.001.003.03' do
416
+ expect(subject.to_xml(SEPA::PAIN_001_003_03)).to validate_against('pain.001.003.03.xsd')
417
+ end
418
+ end
419
+ end
420
+
421
+ context 'xml_schema_header' do
422
+ subject { credit_transfer.to_xml(format) }
423
+
424
+ let(:xml_header) do
425
+ '<?xml version="1.0" encoding="UTF-8"?>' +
426
+ "\n<Document xmlns=\"urn:iso:std:iso:20022:tech:xsd:#{format}\"" +
427
+ ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
428
+ " xsi:schemaLocation=\"urn:iso:std:iso:20022:tech:xsd:#{format} #{format}.xsd\">\n"
429
+ end
430
+
431
+ let(:transaction) do
432
+ {
433
+ name: 'Telekomiker AG',
434
+ iban: 'DE37112589611964645802',
435
+ bic: 'PBNKDEFF370',
436
+ amount: 102.50,
437
+ currency: 'CHF'
438
+ }
439
+ end
440
+
441
+ before do
442
+ credit_transfer.add_transaction transaction
443
+ end
444
+
445
+ context "when format is #{SEPA::PAIN_001_001_03}" do
446
+ let(:format) { SEPA::PAIN_001_001_03 }
447
+
448
+ it 'should return correct header' do
449
+ is_expected.to start_with(xml_header)
450
+ end
451
+ end
452
+
453
+ context "when format is #{SEPA::PAIN_001_002_03}" do
454
+ let(:format) { SEPA::PAIN_001_002_03 }
455
+ let(:transaction) do
456
+ {
457
+ name: 'Telekomiker AG',
458
+ bic: 'PBNKDEFF370',
459
+ iban: 'DE37112589611964645802',
460
+ amount: 102.50,
461
+ reference: 'XYZ-1234/123',
462
+ remittance_information: 'Rechnung vom 22.08.2013'
463
+ }
464
+ end
465
+
466
+ it 'should return correct header' do
467
+ is_expected.to start_with(xml_header)
468
+ end
469
+ end
470
+
471
+ context "when format is #{SEPA::PAIN_001_003_03}" do
472
+ let(:format) { SEPA::PAIN_001_003_03 }
473
+ let(:transaction) do
474
+ {
475
+ name: 'Telekomiker AG',
476
+ bic: 'PBNKDEFF370',
477
+ iban: 'DE37112589611964645802',
478
+ amount: 102.50,
479
+ reference: 'XYZ-1234/123',
480
+ remittance_information: 'Rechnung vom 22.08.2013'
481
+ }
482
+ end
483
+
484
+ it 'should return correct header' do
485
+ is_expected.to start_with(xml_header)
486
+ end
487
+ end
488
+
489
+ context "when format is #{SEPA::PAIN_001_001_03_CH_02}" do
490
+ let(:format) { SEPA::PAIN_001_001_03_CH_02 }
491
+ let(:credit_transfer) do
492
+ SEPA::CreditTransfer.new name: 'Schuldner GmbH',
493
+ iban: 'CH5481230000001998736',
494
+ bic: 'RAIFCH22'
495
+ end
496
+ let(:transaction) do
497
+ {
498
+ name: 'Telekomiker AG',
499
+ iban: 'DE62007620110623852957',
500
+ amount: 102.50,
501
+ currency: 'CHF',
502
+ reference: 'XYZ-1234/123',
503
+ remittance_information: 'Rechnung vom 22.08.2013'
504
+ }
505
+ end
506
+
507
+ let(:xml_header) do
508
+ '<?xml version="1.0" encoding="UTF-8"?>' +
509
+ "\n<Document xmlns=\"http://www.six-interbank-clearing.com/de/#{format}.xsd\"" +
510
+ ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
511
+ " xsi:schemaLocation=\"http://www.six-interbank-clearing.com/de/#{format}.xsd #{format}.xsd\">\n"
512
+ end
513
+
514
+ it 'should return correct header' do
515
+ is_expected.to start_with(xml_header)
516
+ end
517
+ end
518
+ end
519
+ end
520
+ end