Module: SEPA::XmlBuilder

Defined in:
lib/sepa_rator/concerns/xml_builder.rb

Overview

Collection of stateless helpers used by builder stages to emit common XML fragments (addresses, contacts, agent BIC, remittance info, etc.). Most helpers are data-only; ‘build_agent_bic` is the exception that takes a profile to select the right BIC tag and LEI emission.

Constant Summary collapse

POSTAL_ADDRESS_FIELDS =

Element order follows PostalAddress27 XSD sequence (the superset). Fields absent in older schemas are rejected by XSD validation.

[
  %i[CareOf care_of],
  %i[Dept department],
  %i[SubDept sub_department],
  %i[StrtNm street_name],
  %i[BldgNb building_number],
  %i[BldgNm building_name],
  %i[Flr floor],
  %i[UnitNb unit_number],
  %i[PstBx post_box],
  %i[Room room],
  %i[PstCd post_code],
  %i[TwnNm town_name],
  %i[TwnLctnNm town_location_name],
  %i[DstrctNm district_name],
  %i[CtrySubDvsn country_sub_division],
  %i[Ctry country_code],
  %i[AdrLine address_line1],
  %i[AdrLine address_line2]
].freeze
CONTACT_DETAILS_FIELDS =

Element order follows Contact13 XSD sequence (the superset). Othr (OtherContact1) and PrefrdMtd are handled separately.

[
  %i[NmPrfx name_prefix],
  %i[Nm name],
  %i[PhneNb phone_number],
  %i[MobNb mobile_number],
  %i[FaxNb fax_number],
  %i[URLAdr url_address],
  %i[EmailAdr email_address],
  %i[EmailPurp email_purpose],
  %i[JobTitl job_title],
  %i[Rspnsblty responsibility],
  %i[Dept department]
].freeze

Class Method Summary collapse

Class Method Details

.build_agent_bic(builder, bic, profile, fallback: true, lei: nil) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 61

def build_agent_bic(builder, bic, profile, fallback: true, lei: nil)
  lei_emitted = lei && profile.supports?(:lei)

  builder.FinInstnId do
    # XSD sequence: BICFI/BIC → ClrSysMmbId → LEI → Nm → PstlAdr → Othr
    builder.__send__(profile.features.bic_tag, bic) if bic
    builder.LEI(lei) if lei_emitted
    if !bic && !lei_emitted && fallback
      builder.Othr do
        builder.Id('NOTPROVIDED')
      end
    end
  end
end

.build_contact_details(builder, contact_details) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 103

def build_contact_details(builder, contact_details)
  return unless contact_details

  builder.CtctDtls do
    CONTACT_DETAILS_FIELDS.each do |xml_tag, attr|
      value = contact_details.public_send(attr)
      builder.__send__(xml_tag, value) if value
    end
    contact_details.other_contacts&.each do |contact|
      builder.Othr do
        builder.ChanlTp(contact[:channel_type])
        builder.Id(contact[:id]) if contact[:id]
      end
    end
    builder.PrefrdMtd(contact_details.preferred_method) if contact_details.preferred_method
  end
end

.build_creditor_reference_information(builder, transaction) ⇒ Object



92
93
94
95
96
97
98
99
100
101
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 92

def build_creditor_reference_information(builder, transaction)
  builder.CdtrRefInf do
    ref_type = transaction.structured_remittance_reference_type || 'SCOR'
    builder.Tp do
      builder.CdOrPrtry { builder.Cd(ref_type) }
      builder.Issr(transaction.structured_remittance_issuer) if transaction.structured_remittance_issuer
    end
    builder.Ref(transaction.structured_remittance_information)
  end
end

.build_iban_account(builder, tag, iban) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 127

def (builder, tag, iban)
  builder.__send__(tag) do
    builder.Id do
      builder.IBAN(iban)
    end
  end
end

.build_postal_address(builder, address) ⇒ Object



50
51
52
53
54
55
56
57
58
59
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 50

def build_postal_address(builder, address)
  return unless address

  builder.PstlAdr do
    POSTAL_ADDRESS_FIELDS.each do |xml_tag, attr|
      value = address.public_send(attr)
      builder.__send__(xml_tag, value) if value
    end
  end
end

.build_purpose(builder, purpose_code) ⇒ Object



121
122
123
124
125
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 121

def build_purpose(builder, purpose_code)
  return unless purpose_code

  builder.Purp { builder.Cd(purpose_code) }
end

.build_remittance_information(builder, transaction) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 76

def build_remittance_information(builder, transaction)
  has_structured = transaction.structured_remittance_information || transaction.additional_remittance_information
  return unless transaction.remittance_information || has_structured

  builder.RmtInf do
    if has_structured
      builder.Strd do
        build_creditor_reference_information(builder, transaction) if transaction.structured_remittance_information
        Array(transaction.additional_remittance_information).each { |info| builder.AddtlRmtInf(info) }
      end
    else
      builder.Ustrd(transaction.remittance_information)
    end
  end
end

.format_amount(value) ⇒ Object



135
136
137
# File 'lib/sepa_rator/concerns/xml_builder.rb', line 135

def format_amount(value)
  format('%.2f', value)
end