diff --git a/lib/sepa_king/account/creditor_account.rb b/lib/sepa_king/account/creditor_account.rb index 6bede37..af49005 100644 --- a/lib/sepa_king/account/creditor_account.rb +++ b/lib/sepa_king/account/creditor_account.rb @@ -3,6 +3,10 @@ module SEPA class CreditorAccount < Account attr_accessor :creditor_identifier + def identifier + creditor_identifier + end + validates_with CreditorIdentifierValidator, message: "%{value} is invalid" end end diff --git a/lib/sepa_king/account/debtor_account.rb b/lib/sepa_king/account/debtor_account.rb index be98b12..56bcfe4 100644 --- a/lib/sepa_king/account/debtor_account.rb +++ b/lib/sepa_king/account/debtor_account.rb @@ -1,5 +1,12 @@ # encoding: utf-8 module SEPA class DebtorAccount < Account + attr_accessor :debtor_identifier + + def identifier + debtor_identifier + end + + validates_with DebtorIdentifierValidator, message: "%{value} is invalid" end end diff --git a/lib/sepa_king/message.rb b/lib/sepa_king/message.rb index bdd3084..3b9e241 100644 --- a/lib/sepa_king/message.rb +++ b/lib/sepa_king/message.rb @@ -142,10 +142,13 @@ def build_group_header(builder) builder.Id do builder.OrgId do builder.Othr do - builder.Id(account.creditor_identifier) + builder.Id(account.identifier) + builder.SchmeNm do + builder.Cd('CUST') + end end end - end if account.respond_to? :creditor_identifier + end if account.identifier end end end diff --git a/lib/sepa_king/message/credit_transfer.rb b/lib/sepa_king/message/credit_transfer.rb index bddd701..31fd7df 100644 --- a/lib/sepa_king/message/credit_transfer.rb +++ b/lib/sepa_king/message/credit_transfer.rb @@ -11,9 +11,10 @@ class CreditTransfer < Message # Find groups of transactions which share the same values of some attributes def transaction_group(transaction) { requested_date: transaction.requested_date, - batch_booking: transaction.batch_booking, - service_level: transaction.service_level, - category_purpose: transaction.category_purpose + batch_booking: transaction.batch_booking, + service_level: transaction.service_level, + category_purpose: transaction.category_purpose, + account: transaction.debtor_account || account } end @@ -41,17 +42,27 @@ def build_payment_informations(builder) end builder.ReqdExctnDt(group[:requested_date].iso8601) builder.Dbtr do - builder.Nm(account.name) + builder.Nm(group[:account].name) + builder.Id do + builder.OrgId do + builder.Othr do + builder.Id(group[:account].debtor_identifier) + builder.SchmeNm do + builder.Cd('CUST') + end + end + end + end if group[:account].debtor_identifier end builder.DbtrAcct do builder.Id do - builder.IBAN(account.iban) + builder.IBAN(group[:account].iban) end end builder.DbtrAgt do builder.FinInstnId do - if account.bic - builder.BIC(account.bic) + if group[:account].bic + builder.BIC(group[:account].bic) else builder.Othr do builder.Id('NOTPROVIDED') diff --git a/lib/sepa_king/transaction/credit_transfer_transaction.rb b/lib/sepa_king/transaction/credit_transfer_transaction.rb index 8c031c2..167ff11 100644 --- a/lib/sepa_king/transaction/credit_transfer_transaction.rb +++ b/lib/sepa_king/transaction/credit_transfer_transaction.rb @@ -3,12 +3,19 @@ module SEPA class CreditTransferTransaction < Transaction attr_accessor :service_level, :creditor_address, - :category_purpose + :category_purpose, + :debtor_account validates_inclusion_of :service_level, :in => %w(SEPA URGP), :allow_nil => true validates_length_of :category_purpose, within: 1..4, allow_nil: true - validate { |t| t.validate_requested_date_after(Date.today) } + validate do |t| + t.validate_requested_date_after(Date.today) + + if debtor_account + errors.add(:debtor_account, 'is not correct') unless debtor_account.valid? + end + end def initialize(attributes = {}) super diff --git a/lib/sepa_king/validator.rb b/lib/sepa_king/validator.rb index 1ab0a6f..ead6b14 100644 --- a/lib/sepa_king/validator.rb +++ b/lib/sepa_king/validator.rb @@ -58,6 +58,21 @@ def valid?(creditor_identifier) end end + class DebtorIdentifierValidator < ActiveModel::Validator + def validate(record) + field_name = options[:field_name] || :debtor_identifier + value = record.send(field_name) + + unless valid?(value) + record.errors.add(field_name, :invalid, message: options[:message]) + end + end + + def valid?(debtor_identifier) + debtor_identifier.to_s.length <= 35 # Field is Max35Text + end + end + class MandateIdentifierValidator < ActiveModel::Validator REGEX = %r{\A[A-Za-z0-9 +?/:().,'-]{1,35}\z} diff --git a/spec/credit_transfer_spec.rb b/spec/credit_transfer_spec.rb index 3518279..36fabe8 100644 --- a/spec/credit_transfer_spec.rb +++ b/spec/credit_transfer_spec.rb @@ -331,6 +331,33 @@ end end + context 'with transactions containing different debtor_account' do + subject do + sdd = credit_transfer + + debtor_account = SEPA::DebtorAccount.new( name: 'Debtor Inc.', + bic: 'RABONL2U', + iban: 'NL08RABO0135742099', + debtor_identifier: '8001011234' + ) + + sdd.add_transaction(credit_transfer_transaction) + sdd.add_transaction(credit_transfer_transaction.merge(debtor_account: debtor_account)) + sdd.add_transaction(credit_transfer_transaction.merge(debtor_account: debtor_account)) + + sdd.to_xml + end + + it 'should contain two payment_informations with ' do + expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/Dbtr/Nm', 'Schuldner GmbH') + expect(subject).not_to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[1]/Dbtr/Id/OrgId/Othr/Id') + expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/Dbtr/Nm', 'Debtor Inc.') + expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/Dbtr/Id/OrgId/Othr/Id', '8001011234') + expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/Dbtr/Id/OrgId/Othr/SchmeNm/Cd', 'CUST') + expect(subject).to have_xml('//Document/CstmrCdtTrfInitn/PmtInf[2]/CdtTrfTxInf[2]/Cdtr/Nm') # Check that we have two CdtTrfTxInf + end + end + context 'with instruction given' do subject do sct = credit_transfer diff --git a/spec/debtor_account_spec.rb b/spec/debtor_account_spec.rb index 1c46ea9..c1c9e6a 100644 --- a/spec/debtor_account_spec.rb +++ b/spec/debtor_account_spec.rb @@ -9,4 +9,14 @@ iban: 'DE87200500001234567890' ).to be_valid end + + describe :debtor_identifier do + it 'should accept valid value' do + expect(SEPA::DebtorAccount).to accept('a'*35, for: :debtor_identifier) + end + + it 'should not accept invalid value' do + expect(SEPA::DebtorAccount).not_to accept('a'*36, for: :debtor_identifier) + end + end end