sps_king 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|