sps_king 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +32 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +24 -0
- data/README.md +246 -0
- data/Rakefile +6 -0
- data/gemfiles/Gemfile-activemodel-3.1.x +5 -0
- data/gemfiles/Gemfile-activemodel-3.2.x +5 -0
- data/gemfiles/Gemfile-activemodel-4.0.x +5 -0
- data/gemfiles/Gemfile-activemodel-4.1.x +5 -0
- data/gemfiles/Gemfile-activemodel-4.2.x +5 -0
- data/gemfiles/Gemfile-activemodel-5.0.x +5 -0
- data/gemfiles/Gemfile-activemodel-5.1.x +5 -0
- data/gemfiles/Gemfile-activemodel-5.2.x +5 -0
- data/lib/schema/pain.001.001.03.ch.02.xsd +1212 -0
- data/lib/schema/pain.008.001.02.ch.03.xsd +784 -0
- data/lib/sps_king.rb +22 -0
- data/lib/sps_king/account.rb +24 -0
- data/lib/sps_king/account/creditor_account.rb +11 -0
- data/lib/sps_king/account/creditor_address.rb +37 -0
- data/lib/sps_king/account/debtor_account.rb +5 -0
- data/lib/sps_king/account/debtor_address.rb +34 -0
- data/lib/sps_king/converter.rb +53 -0
- data/lib/sps_king/error.rb +4 -0
- data/lib/sps_king/message.rb +163 -0
- data/lib/sps_king/message/credit_transfer.rb +140 -0
- data/lib/sps_king/message/direct_debit.rb +177 -0
- data/lib/sps_king/structured_remittance_information.rb +20 -0
- data/lib/sps_king/transaction.rb +59 -0
- data/lib/sps_king/transaction/credit_transfer_transaction.rb +19 -0
- data/lib/sps_king/transaction/direct_debit_transaction.rb +58 -0
- data/lib/sps_king/validator.rb +55 -0
- data/lib/sps_king/version.rb +3 -0
- data/spec/examples/pain.001.001.03.ch.02.xml +172 -0
- data/spec/examples/pain.008.001.02.ch.03.xml +240 -0
- data/spec/lib/sps_king/account/creditor_account_spec.rb +52 -0
- data/spec/lib/sps_king/account/creditor_address_spec.rb +14 -0
- data/spec/lib/sps_king/account/debtor_account_spec.rb +14 -0
- data/spec/lib/sps_king/account/debtor_address_spec.rb +14 -0
- data/spec/lib/sps_king/account_spec.rb +42 -0
- data/spec/lib/sps_king/converter_spec.rb +88 -0
- data/spec/lib/sps_king/message/credit_transfer_spec.rb +350 -0
- data/spec/lib/sps_king/message/direct_debit_spec.rb +483 -0
- data/spec/lib/sps_king/message_spec.rb +128 -0
- data/spec/lib/sps_king/structured_remittance_information_spec.rb +32 -0
- data/spec/lib/sps_king/transaction/credit_transfer_transaction_spec.rb +53 -0
- data/spec/lib/sps_king/transaction/direct_debit_transaction_spec.rb +56 -0
- data/spec/lib/sps_king/transaction_spec.rb +133 -0
- data/spec/lib/sps_king/validation_spec.rb +23 -0
- data/spec/lib/sps_king/validator_spec.rb +78 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/active_model.rb +30 -0
- data/spec/support/custom_matcher.rb +60 -0
- data/spec/support/factories.rb +33 -0
- data/spec/support/validations.rb +27 -0
- data/sps_king.gemspec +31 -0
- metadata +237 -0
data/lib/sps_king.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'date'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'iban-tools'
|
6
|
+
|
7
|
+
require 'sps_king/error'
|
8
|
+
require 'sps_king/converter'
|
9
|
+
require 'sps_king/validator'
|
10
|
+
require 'sps_king/version'
|
11
|
+
require 'sps_king/account'
|
12
|
+
require 'sps_king/account/debtor_account'
|
13
|
+
require 'sps_king/account/debtor_address'
|
14
|
+
require 'sps_king/account/creditor_account'
|
15
|
+
require 'sps_king/account/creditor_address'
|
16
|
+
require 'sps_king/structured_remittance_information'
|
17
|
+
require 'sps_king/transaction'
|
18
|
+
require 'sps_king/transaction/direct_debit_transaction'
|
19
|
+
require 'sps_king/transaction/credit_transfer_transaction'
|
20
|
+
require 'sps_king/message'
|
21
|
+
require 'sps_king/message/direct_debit'
|
22
|
+
require 'sps_king/message/credit_transfer'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SPS
|
3
|
+
class Account
|
4
|
+
include ActiveModel::Validations
|
5
|
+
extend Converter
|
6
|
+
|
7
|
+
attr_accessor :name,
|
8
|
+
:iban,
|
9
|
+
:bic
|
10
|
+
|
11
|
+
convert :name, to: :text
|
12
|
+
|
13
|
+
validates_length_of :name, within: 1..70
|
14
|
+
validates_with BICValidator,
|
15
|
+
IBANValidator,
|
16
|
+
message: "%{value} is invalid"
|
17
|
+
|
18
|
+
def initialize(attributes = {})
|
19
|
+
attributes.each do |name, value|
|
20
|
+
public_send("#{name}=", value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SPS
|
3
|
+
class CreditorAccount < Account
|
4
|
+
attr_accessor :creditor_identifier,
|
5
|
+
:isr_participant_number
|
6
|
+
|
7
|
+
validates_with CreditorIdentifierValidator,
|
8
|
+
message: "%{value} is invalid"
|
9
|
+
validates_format_of :isr_participant_number, with: /\A\d{9}\z/, allow_nil: true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SPS
|
3
|
+
class CreditorAddress
|
4
|
+
include ActiveModel::Validations
|
5
|
+
extend Converter
|
6
|
+
|
7
|
+
attr_accessor :street_name,
|
8
|
+
:building_number,
|
9
|
+
:post_code,
|
10
|
+
:town_name,
|
11
|
+
:country_code,
|
12
|
+
:address_line1,
|
13
|
+
:address_line2
|
14
|
+
|
15
|
+
convert :street_name, to: :text
|
16
|
+
convert :building_number, to: :text
|
17
|
+
convert :post_code, to: :text
|
18
|
+
convert :town_name, to: :text
|
19
|
+
convert :country_code, to: :text
|
20
|
+
convert :address_line1, to: :text
|
21
|
+
convert :address_line2, to: :text
|
22
|
+
|
23
|
+
validates_length_of :street_name, maximum: 70
|
24
|
+
validates_length_of :building_number, maximum: 16
|
25
|
+
validates_length_of :post_code, maximum: 16
|
26
|
+
validates_length_of :town_name, maximum: 35
|
27
|
+
validates_length_of :country_code, is: 2
|
28
|
+
validates_length_of :address_line1, maximum: 70
|
29
|
+
validates_length_of :address_line2, maximum: 70
|
30
|
+
|
31
|
+
def initialize(attributes = {})
|
32
|
+
attributes.each do |name, value|
|
33
|
+
public_send("#{name}=", value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SPS
|
3
|
+
class DebtorAddress
|
4
|
+
include ActiveModel::Validations
|
5
|
+
extend Converter
|
6
|
+
|
7
|
+
attr_accessor :street_name,
|
8
|
+
:post_code,
|
9
|
+
:town_name,
|
10
|
+
:country_code,
|
11
|
+
:address_line1,
|
12
|
+
:address_line2
|
13
|
+
|
14
|
+
convert :street_name, to: :text
|
15
|
+
convert :post_code, to: :text
|
16
|
+
convert :town_name, to: :text
|
17
|
+
convert :country_code, to: :text
|
18
|
+
convert :address_line1, to: :text
|
19
|
+
convert :address_line2, to: :text
|
20
|
+
|
21
|
+
validates_length_of :street_name, maximum: 70
|
22
|
+
validates_length_of :post_code, maximum: 16
|
23
|
+
validates_length_of :town_name, maximum: 35
|
24
|
+
validates_length_of :country_code, is: 2
|
25
|
+
validates_length_of :address_line1, maximum: 70
|
26
|
+
validates_length_of :address_line2, maximum: 70
|
27
|
+
|
28
|
+
def initialize(attributes = {})
|
29
|
+
attributes.each do |name, value|
|
30
|
+
public_send("#{name}=", value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SPS
|
3
|
+
module Converter
|
4
|
+
def convert(*attributes, options)
|
5
|
+
include InstanceMethods
|
6
|
+
|
7
|
+
method_name = "convert_#{options[:to]}"
|
8
|
+
unless InstanceMethods.method_defined?(method_name)
|
9
|
+
raise ArgumentError.new("Converter '#{options[:to]}' does not exist!")
|
10
|
+
end
|
11
|
+
|
12
|
+
attributes.each do |attribute|
|
13
|
+
define_method "#{attribute}=" do |value|
|
14
|
+
instance_variable_set("@#{attribute}", send(method_name, value))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def convert_text(value)
|
21
|
+
return unless value
|
22
|
+
|
23
|
+
value.to_s.
|
24
|
+
# Replace some special characters described as "Best practices" in Chapter 6.2 of this document:
|
25
|
+
# http://www.europeanpaymentscouncil.eu/index.cfm/knowledge-bank/epc-documents/sepa-requirements-for-an-extended-character-set-unicode-subset-best-practices/
|
26
|
+
gsub('€','E').
|
27
|
+
gsub('@','(at)').
|
28
|
+
gsub('_','-').
|
29
|
+
|
30
|
+
# Replace linebreaks by spaces
|
31
|
+
gsub(/\n+/,' ').
|
32
|
+
|
33
|
+
# Remove all invalid characters
|
34
|
+
gsub(/[^a-zA-Z0-9ÄÖÜäöüß&*$%\ \'\:\?\,\-\(\+\.\)\/]/, '').
|
35
|
+
|
36
|
+
# Remove leading and trailing spaces
|
37
|
+
strip
|
38
|
+
end
|
39
|
+
|
40
|
+
def convert_decimal(value)
|
41
|
+
return unless value
|
42
|
+
value = begin
|
43
|
+
BigDecimal(value.to_s)
|
44
|
+
rescue ArgumentError
|
45
|
+
end
|
46
|
+
|
47
|
+
if value && value.finite? && value > 0
|
48
|
+
value.round(2)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SPS
|
4
|
+
PAIN_008_001_02_CH_03 = 'pain.008.001.02.ch.03'
|
5
|
+
PAIN_001_001_03_CH_02 = 'pain.001.001.03.ch.02'
|
6
|
+
|
7
|
+
class Message
|
8
|
+
include ActiveModel::Validations
|
9
|
+
|
10
|
+
attr_reader :account, :grouped_transactions
|
11
|
+
|
12
|
+
validates_presence_of :transactions
|
13
|
+
validate do |record|
|
14
|
+
record.errors.add(:account, record.account.errors.full_messages) unless record.account.valid?
|
15
|
+
end
|
16
|
+
|
17
|
+
class_attribute :account_class, :transaction_class, :xml_main_tag, :known_schemas
|
18
|
+
|
19
|
+
def initialize(account_options={})
|
20
|
+
@grouped_transactions = {}
|
21
|
+
@account = account_class.new(account_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_transaction(options)
|
25
|
+
transaction = transaction_class.new(options)
|
26
|
+
raise ArgumentError.new(transaction.errors.full_messages.join("\n")) unless transaction.valid?
|
27
|
+
@grouped_transactions[transaction_group(transaction)] ||= []
|
28
|
+
@grouped_transactions[transaction_group(transaction)] << transaction
|
29
|
+
end
|
30
|
+
|
31
|
+
def transactions
|
32
|
+
grouped_transactions.values.flatten
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [String] xml
|
36
|
+
def to_xml(schema_name=self.known_schemas.first)
|
37
|
+
raise SPS::Error.new(errors.full_messages.join("\n")) unless valid?
|
38
|
+
raise SPS::Error.new("Incompatible with schema #{schema_name}!") unless schema_compatible?(schema_name)
|
39
|
+
|
40
|
+
builder = Nokogiri::XML::Builder.new do |builder|
|
41
|
+
builder.Document(xml_schema(schema_name)) do
|
42
|
+
builder.__send__(xml_main_tag) do
|
43
|
+
build_group_header(builder)
|
44
|
+
build_payment_informations(builder)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
validate_final_document!(builder.doc, schema_name)
|
50
|
+
builder.to_xml
|
51
|
+
end
|
52
|
+
|
53
|
+
def amount_total(selected_transactions=transactions)
|
54
|
+
selected_transactions.inject(0) { |sum, t| sum + t.amount }
|
55
|
+
end
|
56
|
+
|
57
|
+
def schema_compatible?(schema_name)
|
58
|
+
raise ArgumentError.new("Schema #{schema_name} is unknown!") unless self.known_schemas.include?(schema_name)
|
59
|
+
|
60
|
+
case schema_name
|
61
|
+
when PAIN_001_001_03_CH_02
|
62
|
+
transactions.all? { |t| t.schema_compatible?(schema_name) }
|
63
|
+
when PAIN_008_001_02_CH_03
|
64
|
+
transactions.all? { |t| t.schema_compatible?(schema_name) } &&
|
65
|
+
!account.iban.to_s.match(/^(CH|LI)/).nil? # Only allowed for switzerland or liechtenstein
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Set unique identifer for the message
|
70
|
+
def message_identification=(value)
|
71
|
+
raise ArgumentError.new('message_identification must be a string!') unless value.is_a?(String)
|
72
|
+
|
73
|
+
regex = /\A([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|\,|\'|\ ]){1,35}\z/
|
74
|
+
raise ArgumentError.new("message_identification does not match #{regex}!") unless value.match(regex)
|
75
|
+
|
76
|
+
@message_identification = value
|
77
|
+
end
|
78
|
+
|
79
|
+
# Get unique identifer for the message (with fallback to a random string)
|
80
|
+
def message_identification
|
81
|
+
@message_identification ||= "SPS-KING/#{SecureRandom.hex(11)}"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Set creation date time for the message
|
85
|
+
# p.s. Rabobank in the Netherlands only accepts the more restricted format [0-9]{4}[-][0-9]{2,2}[-][0-9]{2,2}[T][0-9]{2,2}[:][0-9]{2,2}[:][0-9]{2,2}
|
86
|
+
def creation_date_time=(value)
|
87
|
+
raise ArgumentError.new('creation_date_time must be a string!') unless value.is_a?(String)
|
88
|
+
|
89
|
+
regex = /[0-9]{4}[-][0-9]{2,2}[-][0-9]{2,2}(?:\s|T)[0-9]{2,2}[:][0-9]{2,2}[:][0-9]{2,2}/
|
90
|
+
raise ArgumentError.new("creation_date_time does not match #{regex}!") unless value.match(regex)
|
91
|
+
|
92
|
+
@creation_date_time = value
|
93
|
+
end
|
94
|
+
|
95
|
+
# Get creation date time for the message (with fallback to Time.now.iso8601)
|
96
|
+
def creation_date_time
|
97
|
+
@creation_date_time ||= Time.now.iso8601
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns the id of the batch to which the given transaction belongs
|
101
|
+
# Identified based upon the reference of the transaction
|
102
|
+
def batch_id(transaction_reference)
|
103
|
+
grouped_transactions.each do |group, transactions|
|
104
|
+
if transactions.select { |transaction| transaction.reference == transaction_reference }.any?
|
105
|
+
return payment_information_identification(group)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def batches
|
111
|
+
grouped_transactions.keys.collect { |group| payment_information_identification(group) }
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
# @return {Hash<Symbol=>String>} xml schema information used in output xml
|
116
|
+
def xml_schema(schema_name)
|
117
|
+
{
|
118
|
+
:xmlns => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd",
|
119
|
+
:'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
120
|
+
:'xsi:schemaLocation' => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd #{schema_name}.xsd"
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
def build_group_header(builder)
|
125
|
+
builder.GrpHdr do
|
126
|
+
builder.MsgId(message_identification)
|
127
|
+
builder.CreDtTm(creation_date_time)
|
128
|
+
builder.NbOfTxs(transactions.length)
|
129
|
+
builder.CtrlSum('%.2f' % amount_total)
|
130
|
+
builder.InitgPty do
|
131
|
+
builder.Nm(account.name)
|
132
|
+
builder.Id do
|
133
|
+
builder.OrgId do
|
134
|
+
builder.Othr do
|
135
|
+
builder.Id(account.creditor_identifier)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end if account.respond_to? :creditor_identifier
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Unique and consecutive identifier (used for the <PmntInf> blocks)
|
144
|
+
def payment_information_identification(group)
|
145
|
+
"#{message_identification}/#{grouped_transactions.keys.index(group)+1}"
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns a key to determine the group to which the transaction belongs
|
149
|
+
def transaction_group(transaction)
|
150
|
+
transaction
|
151
|
+
end
|
152
|
+
|
153
|
+
def validate_final_document!(document, schema_name)
|
154
|
+
xsd = Nokogiri::XML::Schema(
|
155
|
+
File.read(
|
156
|
+
File.expand_path("../../../lib/schema/#{schema_name}.xsd", __FILE__)
|
157
|
+
)
|
158
|
+
)
|
159
|
+
errors = xsd.validate(document).map { |error| error.message }
|
160
|
+
raise SPS::Error.new("Incompatible with schema #{schema_name}: #{errors.join(', ')}") if errors.any?
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SPS
|
4
|
+
class CreditTransfer < Message
|
5
|
+
self.account_class = DebtorAccount
|
6
|
+
self.transaction_class = CreditTransferTransaction
|
7
|
+
self.xml_main_tag = 'CstmrCdtTrfInitn'
|
8
|
+
self.known_schemas = [
|
9
|
+
PAIN_001_001_03_CH_02
|
10
|
+
]
|
11
|
+
|
12
|
+
private
|
13
|
+
# Find groups of transactions which share the same values of some attributes
|
14
|
+
def transaction_group(transaction)
|
15
|
+
{
|
16
|
+
requested_date: transaction.requested_date,
|
17
|
+
batch_booking: transaction.batch_booking,
|
18
|
+
service_level: transaction.service_level,
|
19
|
+
category_purpose: transaction.category_purpose
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_payment_informations(builder)
|
24
|
+
# Build a PmtInf block for every group of transactions
|
25
|
+
grouped_transactions.each do |group, transactions|
|
26
|
+
# All transactions with the same requested_date are placed into the same PmtInf block
|
27
|
+
builder.PmtInf do
|
28
|
+
builder.PmtInfId(payment_information_identification(group))
|
29
|
+
builder.PmtMtd('TRF')
|
30
|
+
builder.BtchBookg(group[:batch_booking])
|
31
|
+
builder.NbOfTxs(transactions.length)
|
32
|
+
builder.CtrlSum('%.2f' % amount_total(transactions))
|
33
|
+
builder.PmtTpInf do
|
34
|
+
if group[:service_level]
|
35
|
+
builder.SvcLvl do
|
36
|
+
builder.Cd(group[:service_level])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
if group[:category_purpose]
|
40
|
+
builder.CtgyPurp do
|
41
|
+
builder.Cd(group[:category_purpose])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
builder.ReqdExctnDt(group[:requested_date].iso8601)
|
46
|
+
builder.Dbtr do
|
47
|
+
builder.Nm(account.name)
|
48
|
+
end
|
49
|
+
builder.DbtrAcct do
|
50
|
+
builder.Id do
|
51
|
+
builder.IBAN(account.iban)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
builder.DbtrAgt do
|
55
|
+
builder.FinInstnId do
|
56
|
+
builder.BIC(account.bic)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
builder.ChrgBr('SLEV')
|
60
|
+
|
61
|
+
transactions.each do |transaction|
|
62
|
+
build_transaction(builder, transaction)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_transaction(builder, transaction)
|
69
|
+
builder.CdtTrfTxInf do
|
70
|
+
builder.PmtId do
|
71
|
+
if transaction.instruction.present?
|
72
|
+
builder.InstrId(transaction.instruction)
|
73
|
+
end
|
74
|
+
builder.EndToEndId(transaction.reference)
|
75
|
+
end
|
76
|
+
builder.Amt do
|
77
|
+
builder.InstdAmt('%.2f' % transaction.amount, Ccy: transaction.currency)
|
78
|
+
end
|
79
|
+
if transaction.bic
|
80
|
+
builder.CdtrAgt do
|
81
|
+
builder.FinInstnId do
|
82
|
+
builder.BIC(transaction.bic)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
builder.Cdtr do
|
87
|
+
builder.Nm(transaction.name)
|
88
|
+
if transaction.creditor_address
|
89
|
+
builder.PstlAdr do
|
90
|
+
# Only set the fields that are actually provided.
|
91
|
+
# StrtNm, BldgNb, PstCd, TwnNm provide a structured address
|
92
|
+
# separated into its individual fields.
|
93
|
+
# AdrLine provides the address in free format text.
|
94
|
+
# Both are currently allowed and the actual preference depends on the bank.
|
95
|
+
# Also the fields that are required legally may vary depending on the country
|
96
|
+
# or change over time.
|
97
|
+
if transaction.creditor_address.street_name
|
98
|
+
builder.StrtNm transaction.creditor_address.street_name
|
99
|
+
end
|
100
|
+
|
101
|
+
if transaction.creditor_address.building_number
|
102
|
+
builder.BldgNb transaction.creditor_address.building_number
|
103
|
+
end
|
104
|
+
|
105
|
+
if transaction.creditor_address.post_code
|
106
|
+
builder.PstCd transaction.creditor_address.post_code
|
107
|
+
end
|
108
|
+
|
109
|
+
if transaction.creditor_address.town_name
|
110
|
+
builder.TwnNm transaction.creditor_address.town_name
|
111
|
+
end
|
112
|
+
|
113
|
+
if transaction.creditor_address.country_code
|
114
|
+
builder.Ctry transaction.creditor_address.country_code
|
115
|
+
end
|
116
|
+
|
117
|
+
if transaction.creditor_address.address_line1
|
118
|
+
builder.AdrLine transaction.creditor_address.address_line1
|
119
|
+
end
|
120
|
+
|
121
|
+
if transaction.creditor_address.address_line2
|
122
|
+
builder.AdrLine transaction.creditor_address.address_line2
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
builder.CdtrAcct do
|
128
|
+
builder.Id do
|
129
|
+
builder.IBAN(transaction.iban)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
if transaction.remittance_information
|
133
|
+
builder.RmtInf do
|
134
|
+
builder.Ustrd(transaction.remittance_information)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|