class SEPA::Message
Attributes
account[R]
grouped_transactions[R]
Public Class Methods
new(account_options={})
click to toggle source
# File lib/sepa_king/message.rb, line 24 def initialize(account_options={}) @grouped_transactions = {} @account = account_class.new(account_options) end
Public Instance Methods
add_transaction(options)
click to toggle source
# File lib/sepa_king/message.rb, line 29 def add_transaction(options) transaction = transaction_class.new(options) raise ArgumentError.new(transaction.errors.full_messages.join("\n")) unless transaction.valid? @grouped_transactions[transaction_group(transaction)] ||= [] @grouped_transactions[transaction_group(transaction)] << transaction end
amount_total(selected_transactions=transactions)
click to toggle source
# File lib/sepa_king/message.rb, line 58 def amount_total(selected_transactions=transactions) selected_transactions.inject(0) { |sum, t| sum + t.amount } end
batch_id(transaction_reference)
click to toggle source
Returns the id of the batch to which the given transaction belongs Identified based upon the reference of the transaction
# File lib/sepa_king/message.rb, line 106 def batch_id(transaction_reference) grouped_transactions.each do |group, transactions| if transactions.select { |transaction| transaction.reference == transaction_reference }.any? return payment_information_identification(group) end end end
batches()
click to toggle source
# File lib/sepa_king/message.rb, line 114 def batches grouped_transactions.keys.collect { |group| payment_information_identification(group) } end
creation_date_time()
click to toggle source
Get creation date time for the message (with fallback to Time.now.iso8601)
# File lib/sepa_king/message.rb, line 100 def creation_date_time @creation_date_time ||= Time.now.iso8601 end
creation_date_time=(value)
click to toggle source
Set creation date time for the message p.s. Rabobank in the Netherlands only accepts the more restricted format [0-9]4[0-9]2,2[0-9]2,2[0-9]2,2[0-9]2,2[0-9]{2,2}
# File lib/sepa_king/message.rb, line 90 def creation_date_time=(value) raise ArgumentError.new('creation_date_time must be a string!') unless value.is_a?(String) 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}/ raise ArgumentError.new("creation_date_time does not match #{regex}!") unless value.match(regex) @creation_date_time = value end
message_identification()
click to toggle source
Get unique identifer for the message (with fallback to a random string)
# File lib/sepa_king/message.rb, line 84 def message_identification @message_identification ||= "SEPA-KING/#{SecureRandom.hex(11)}" end
message_identification=(value)
click to toggle source
Set unique identifer for the message
# File lib/sepa_king/message.rb, line 74 def message_identification=(value) raise ArgumentError.new('message_identification must be a string!') unless value.is_a?(String) regex = /\A([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|\,|\'|\ ]){1,35}\z/ raise ArgumentError.new("message_identification does not match #{regex}!") unless value.match(regex) @message_identification = value end
schema_compatible?(schema_name)
click to toggle source
# File lib/sepa_king/message.rb, line 62 def schema_compatible?(schema_name) raise ArgumentError.new("Schema #{schema_name} is unknown!") unless self.known_schemas.include?(schema_name) case schema_name when PAIN_001_002_03, PAIN_008_002_02, PAIN_001_001_03, PAIN_001_001_03_CH_02 account.bic.present? && transactions.all? { |t| t.schema_compatible?(schema_name) } when PAIN_001_003_03, PAIN_008_003_02, PAIN_008_001_02 transactions.all? { |t| t.schema_compatible?(schema_name) } end end
to_xml(schema_name=self.known_schemas.first)
click to toggle source
@return [String] xml
# File lib/sepa_king/message.rb, line 41 def to_xml(schema_name=self.known_schemas.first) raise SEPA::Error.new(errors.full_messages.join("\n")) unless valid? raise SEPA::Error.new("Incompatible with schema #{schema_name}!") unless schema_compatible?(schema_name) builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |builder| builder.Document(xml_schema(schema_name)) do builder.__send__(xml_main_tag) do build_group_header(builder) build_payment_informations(builder) end end end validate_final_document!(builder.doc, schema_name) builder.to_xml end
transactions()
click to toggle source
# File lib/sepa_king/message.rb, line 36 def transactions grouped_transactions.values.flatten end
Private Instance Methods
build_group_header(builder)
click to toggle source
# File lib/sepa_king/message.rb, line 134 def build_group_header(builder) builder.GrpHdr do builder.MsgId(message_identification) builder.CreDtTm(creation_date_time) builder.NbOfTxs(transactions.length) builder.CtrlSum('%.2f' % amount_total) builder.InitgPty do builder.Nm(account.name) builder.Id do builder.OrgId do builder.Othr do builder.Id(account.creditor_identifier) end end end if account.respond_to? :creditor_identifier end end end
payment_information_identification(group)
click to toggle source
Unique and consecutive identifier (used for the <PmntInf> blocks)
# File lib/sepa_king/message.rb, line 154 def payment_information_identification(group) "#{message_identification}/#{grouped_transactions.keys.index(group)+1}" end
transaction_group(transaction)
click to toggle source
Returns a key to determine the group to which the transaction belongs
# File lib/sepa_king/message.rb, line 159 def transaction_group(transaction) transaction end
validate_final_document!(document, schema_name)
click to toggle source
# File lib/sepa_king/message.rb, line 163 def validate_final_document!(document, schema_name) xsd = Nokogiri::XML::Schema(File.read(File.expand_path("../../../lib/schema/#{schema_name}.xsd", __FILE__))) errors = xsd.validate(document).map { |error| error.message } raise SEPA::Error.new("Incompatible with schema #{schema_name}: #{errors.join(', ')}") if errors.any? end
xml_schema(schema_name)
click to toggle source
@return {Hash<Symbol=>String>} xml schema information used in output xml
# File lib/sepa_king/message.rb, line 120 def xml_schema(schema_name) return { :xmlns => "urn:iso:std:iso:20022:tech:xsd:#{schema_name}", :'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', :'xsi:schemaLocation' => "urn:iso:std:iso:20022:tech:xsd:#{schema_name} #{schema_name}.xsd" } unless schema_name == PAIN_001_001_03_CH_02 { xmlns: 'http://www.six-interbank-clearing.com/de/pain.001.001.03.ch.02.xsd', 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:schemaLocation': 'http://www.six-interbank-clearing.com/de/pain.001.001.03.ch.02.xsd pain.001.001.03.ch.02.xsd' } end