Skip to content

Commit

Permalink
Add Currency support for debits and credits (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
skateinmars authored and ledermann committed Aug 11, 2017
1 parent 2465c71 commit a9f481b
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 13 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,14 @@ sdd.add_transaction(
# String, max. 34 chars
iban: 'DE21500500009876543210',

# Amount in EUR
# Amount
# Number with two decimal digit
amount: 39.99,

# OPTIONAL: Currency, EUR by default (ISO 4217 standard)
# String, 3 char
currency: 'EUR',

# OPTIONAL: Instruction Identification, will not be submitted to the debtor
# String, max. 35 char
instruction: '12345',
Expand Down Expand Up @@ -166,10 +170,14 @@ sct.add_transaction(
# String, max. 34 chars
iban: 'DE37112589611964645802',

# Amount in EUR
# Amount
# Number with two decimal digit
amount: 102.50,

# OPTIONAL: Currency, EUR by default (ISO 4217 standard)
# String, 3 char
currency: 'EUR',

# OPTIONAL: Instruction Identification, will not be submitted to the creditor
# String, max. 35 char
instruction: '12345',
Expand Down
2 changes: 1 addition & 1 deletion lib/sepa_king/message/credit_transfer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def build_transaction(builder, transaction)
builder.EndToEndId(transaction.reference)
end
builder.Amt do
builder.InstdAmt('%.2f' % transaction.amount, Ccy: 'EUR')
builder.InstdAmt('%.2f' % transaction.amount, Ccy: transaction.currency)
end
if transaction.bic
builder.CdtrAgt do
Expand Down
2 changes: 1 addition & 1 deletion lib/sepa_king/message/direct_debit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def build_transaction(builder, transaction)
end
builder.EndToEndId(transaction.reference)
end
builder.InstdAmt('%.2f' % transaction.amount, Ccy: 'EUR')
builder.InstdAmt('%.2f' % transaction.amount, Ccy: transaction.currency)
builder.DrctDbtTx do
builder.MndtRltdInf do
builder.MndtId(transaction.mandate_id)
Expand Down
4 changes: 3 additions & 1 deletion lib/sepa_king/transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ class Transaction

DEFAULT_REQUESTED_DATE = Date.new(1999, 1, 1).freeze

attr_accessor :name, :iban, :bic, :amount, :instruction, :reference, :remittance_information, :requested_date, :batch_booking
attr_accessor :name, :iban, :bic, :amount, :instruction, :reference, :remittance_information, :requested_date, :batch_booking, :currency
convert :name, :instruction, :reference, :remittance_information, to: :text
convert :amount, to: :decimal

validates_length_of :name, within: 1..70
validates_length_of :currency, is: 3
validates_length_of :instruction, within: 1..35, allow_nil: true
validates_length_of :reference, within: 1..35, allow_nil: true
validates_length_of :remittance_information, within: 1..140, allow_nil: true
Expand All @@ -27,6 +28,7 @@ def initialize(attributes = {})
self.requested_date ||= DEFAULT_REQUESTED_DATE
self.reference ||= 'NOTPROVIDED'
self.batch_booking = true if self.batch_booking.nil?
self.currency ||= 'EUR'
end

protected
Expand Down
6 changes: 4 additions & 2 deletions lib/sepa_king/transaction/credit_transfer_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ def initialize(attributes = {})

def schema_compatible?(schema_name)
case schema_name
when PAIN_001_001_03, PAIN_001_002_03
when PAIN_001_001_03
self.bic.present? && self.service_level == 'SEPA'
when PAIN_001_002_03
self.bic.present? && self.service_level == 'SEPA' && self.currency == 'EUR'
when PAIN_001_003_03
true
self.currency == 'EUR'
end
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/sepa_king/transaction/direct_debit_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ def initialize(attributes = {})
def schema_compatible?(schema_name)
case schema_name
when PAIN_008_002_02
self.bic.present? && %w(CORE B2B).include?(self.local_instrument)
when PAIN_008_003_02, PAIN_008_001_02
self.bic.present? && %w(CORE B2B).include?(self.local_instrument) && self.currency == 'EUR'
when PAIN_008_003_02
self.currency == 'EUR'
when PAIN_008_001_02
true
end
end
Expand Down
39 changes: 39 additions & 0 deletions spec/credit_transfer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,45 @@
expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/PmtId/InstrId', '1234/ABC')
end
end

context 'with a different currency given' do
subject do
sct = credit_transfer

sct.add_transaction name: 'Telekomiker AG',
iban: 'DE37112589611964645802',
bic: 'PBNKDEFF370',
amount: 102.50,
currency: 'CHF'

sct
end

it 'should validate against pain.001.001.03' do
expect(subject.to_xml('pain.001.001.03')).to validate_against('pain.001.001.03.xsd')
end

it 'should have a CHF Ccy' do
doc = Nokogiri::XML(subject.to_xml('pain.001.001.03'))
doc.remove_namespaces!

nodes = doc.xpath('//Document/CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf[1]/Amt/InstdAmt')
expect(nodes.length).to eql(1)
expect(nodes.first.attribute('Ccy').value).to eql('CHF')
end

it 'should fail for pain.001.002.03' do
expect {
subject.to_xml(SEPA::PAIN_001_002_03)
}.to raise_error(RuntimeError)
end

it 'should fail for pain.001.003.03' do
expect {
subject.to_xml(SEPA::PAIN_001_003_03)
}.to raise_error(RuntimeError)
end
end
end
end
end
15 changes: 13 additions & 2 deletions spec/credit_transfer_transaction_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,30 @@

describe :schema_compatible? do
context 'for pain.001.003.03' do
it 'should success' do
it 'should succeed' do
expect(SEPA::CreditTransferTransaction.new({})).to be_schema_compatible('pain.001.003.03')
end

it 'should fail for invalid attributes' do
expect(SEPA::CreditTransferTransaction.new(:currency => 'CHF')).not_to be_schema_compatible('pain.001.003.03')
end
end

context 'pain.001.002.03' do
it 'should success for valid attributes' do
it 'should succeed for valid attributes' do
expect(SEPA::CreditTransferTransaction.new(:bic => 'SPUEDE2UXXX', :service_level => 'SEPA')).to be_schema_compatible('pain.001.002.03')
end

it 'should fail for invalid attributes' do
expect(SEPA::CreditTransferTransaction.new(:bic => nil)).not_to be_schema_compatible('pain.001.002.03')
expect(SEPA::CreditTransferTransaction.new(:bic => 'SPUEDE2UXXX', :service_level => 'URGP')).not_to be_schema_compatible('pain.001.002.03')
expect(SEPA::CreditTransferTransaction.new(:bic => 'SPUEDE2UXXX', :currency => 'CHF')).not_to be_schema_compatible('pain.001.002.03')
end
end

context 'for pain.001.001.03' do
it 'should succeed for valid attributes' do
expect(SEPA::CreditTransferTransaction.new(:bic => 'SPUEDE2UXXX', :currency => 'CHF')).to be_schema_compatible('pain.001.001.03')
end
end
end
Expand Down
35 changes: 35 additions & 0 deletions spec/direct_debit_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,41 @@
expect(subject).to have_xml('//Document/CstmrDrctDbtInitn/PmtInf/DrctDbtTxInf[1]/PmtId/InstrId', '1234/ABC')
end
end

context 'with a different currency given' do
subject do
sct = direct_debit

sct.add_transaction(direct_debt_transaction.merge(instruction: '1234/ABC', currency: 'SEK'))

sct
end

it 'should validate against pain.001.001.03' do
expect(subject.to_xml(SEPA::PAIN_008_001_02)).to validate_against('pain.008.001.02.xsd')
end

it 'should have a CHF Ccy' do
doc = Nokogiri::XML(subject.to_xml('pain.008.001.02'))
doc.remove_namespaces!

nodes = doc.xpath('//Document/CstmrDrctDbtInitn/PmtInf/DrctDbtTxInf[1]/InstdAmt')
expect(nodes.length).to eql(1)
expect(nodes.first.attribute('Ccy').value).to eql('SEK')
end

it 'should fail for pain.008.002.02' do
expect {
subject.to_xml(SEPA::PAIN_008_002_02)
}.to raise_error(RuntimeError)
end

it 'should fail for pain.008.003.02' do
expect {
subject.to_xml(SEPA::PAIN_008_003_02)
}.to raise_error(RuntimeError)
end
end
end
end
end
15 changes: 13 additions & 2 deletions spec/direct_debit_transaction_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,30 @@

describe :schema_compatible? do
context 'for pain.008.003.02' do
it 'should success' do
it 'should succeed' do
expect(SEPA::DirectDebitTransaction.new({})).to be_schema_compatible('pain.008.003.02')
end

it 'should fail for invalid attributes' do
expect(SEPA::DirectDebitTransaction.new(:currency => 'CHF')).not_to be_schema_compatible('pain.001.003.03')
end
end

context 'for pain.008.002.02' do
it 'should success for valid attributes' do
it 'should succeed for valid attributes' do
expect(SEPA::DirectDebitTransaction.new(:bic => 'SPUEDE2UXXX', :local_instrument => 'CORE')).to be_schema_compatible('pain.008.002.02')
end

it 'should fail for invalid attributes' do
expect(SEPA::DirectDebitTransaction.new(:bic => nil)).not_to be_schema_compatible('pain.008.002.02')
expect(SEPA::DirectDebitTransaction.new(:bic => 'SPUEDE2UXXX', :local_instrument => 'COR1')).not_to be_schema_compatible('pain.008.002.02')
expect(SEPA::DirectDebitTransaction.new(:bic => 'SPUEDE2UXXX', :currency => 'CHF')).not_to be_schema_compatible('pain.008.002.02')
end
end

context 'for pain.008.001.02' do
it 'should succeed for valid attributes' do
expect(SEPA::DirectDebitTransaction.new(:bic => 'SPUEDE2UXXX', :currency => 'CHF')).to be_schema_compatible('pain.008.001.02')
end
end
end
Expand Down
10 changes: 10 additions & 0 deletions spec/transaction_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,14 @@
expect(SEPA::Transaction).not_to accept('', 'X' * 141, for: :remittance_information)
end
end

context 'Currency' do
it 'should allow valid values' do
expect(SEPA::Transaction).to accept('EUR', 'CHF', 'SEK', for: :currency)
end

it 'should not allow invalid values' do
expect(SEPA::Transaction).not_to accept('', 'EURO', 'ABCDEF', for: :currency)
end
end
end

0 comments on commit a9f481b

Please sign in to comment.