brot 0.1.1 → 0.2.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.
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test_helper'
4
+
5
+ EXPECTED_DOCUMENT_NAMESPACES = {
6
+ Brot::PainVersion::PAIN_001_001_12 => 'urn:iso:std:iso:20022:tech:xsd:pain.001.001.12',
7
+ Brot::PainVersion::PAIN_001_003_03 => 'urn:iso:std:iso:20022:tech:xsd:pain.001.003.03'
8
+ }.freeze
9
+ DOCUMENT_ATTRIBUTES = {
10
+ message_id: 'MSG-20260313-01',
11
+ payment_information_id: 'PMT-20260313-01',
12
+ initiating_party_name: 'Example Debtor GmbH',
13
+ debtor_name: 'Example Debtor GmbH',
14
+ debtor_iban: 'DE12500105170648489890',
15
+ debtor_bic: 'INGDDEFFXXX',
16
+ requested_execution_date: Date.new(2026, 3, 13),
17
+ created_at: Time.utc(2026, 3, 13, 12, 0, 0)
18
+ }.freeze
19
+ TRANSFER_ATTRIBUTES = {
20
+ amount: '1250.50',
21
+ creditor_name: 'Example Supplier GmbH',
22
+ creditor_iban: 'DE89370400440532013000',
23
+ creditor_bic: 'COBADEFFXXX',
24
+ end_to_end_id: 'INV-2026-0001',
25
+ remittance_information: 'Invoice 2026-0001',
26
+ instruction_id: 'INSTR-2026-0001'
27
+ }.freeze
28
+
29
+ class DocumentTest < Minitest::Test
30
+ def test_defaults_to_the_latest_supported_version = assert_equal(Brot::PainVersion::PAIN_001_003_03, document.version)
31
+
32
+ def test_accepts_a_pain_version_object
33
+ assert_equal Brot::PainVersion::PAIN_001_001_12,
34
+ document(version: Brot::PainVersion::PAIN_001_001_12).version
35
+ end
36
+
37
+ def test_serializes_the_expected_namespace_for_each_version
38
+ EXPECTED_DOCUMENT_NAMESPACES.each do |version, namespace|
39
+ assert_equal namespace, parsed_document(version).root.namespace.href
40
+ end
41
+ end
42
+
43
+ def test_serializes_group_header_values_for_each_version
44
+ assert_for_each_version('//ns:GrpHdr/ns:MsgId', 'MSG-20260313-01')
45
+ assert_for_each_version('//ns:GrpHdr/ns:NbOfTxs', '1')
46
+ assert_for_each_version('//ns:GrpHdr/ns:CtrlSum', '1250.50')
47
+ end
48
+
49
+ def test_serializes_payment_metadata_for_each_version
50
+ assert_for_each_version('//ns:PmtTpInf/ns:SvcLvl/ns:Cd', 'SEPA')
51
+ assert_for_each_version('//ns:Amt/ns:InstdAmt', '1250.50')
52
+
53
+ EXPECTED_DOCUMENT_NAMESPACES.each_key do |version|
54
+ assert_equal 'EUR',
55
+ parsed_document(version).at_xpath('//ns:Amt/ns:InstdAmt', ns(version)).attribute('Ccy').value
56
+ end
57
+ end
58
+
59
+ def test_serializes_remittance_information_for_each_version
60
+ assert_for_each_version('//ns:RmtInf/ns:Ustrd', 'Invoice 2026-0001')
61
+ end
62
+
63
+ def test_serializes_version_specific_requested_execution_dates
64
+ assert_xpath(Brot::PainVersion::PAIN_001_001_12, '//ns:ReqdExctnDt/ns:Dt', '2026-03-13')
65
+ assert_xpath(Brot::PainVersion::PAIN_001_003_03, '//ns:ReqdExctnDt', '2026-03-13')
66
+ end
67
+
68
+ def test_serializes_version_specific_bic_element_names
69
+ assert_xpath(Brot::PainVersion::PAIN_001_001_12, '//ns:DbtrAgt/ns:FinInstnId/ns:BICFI', 'INGDDEFFXXX')
70
+ assert_xpath(Brot::PainVersion::PAIN_001_003_03, '//ns:DbtrAgt/ns:FinInstnId/ns:BIC', 'INGDDEFFXXX')
71
+ end
72
+
73
+ def test_serializes_notprovided_when_bic_is_missing_for_each_version
74
+ EXPECTED_DOCUMENT_NAMESPACES.each_key do |version|
75
+ parsed = Nokogiri::XML(document(version:, debtor_bic: nil, creditor_bic: nil).to_xml)
76
+
77
+ assert_equal 'NOTPROVIDED', parsed.at_xpath('//ns:DbtrAgt/ns:FinInstnId/ns:Othr/ns:Id', ns(version)).content
78
+ assert_equal 'NOTPROVIDED', parsed.at_xpath('//ns:CdtrAgt/ns:FinInstnId/ns:Othr/ns:Id', ns(version)).content
79
+ end
80
+ end
81
+
82
+ def test_validates_generated_xml_against_the_bundled_xsd_for_each_version
83
+ EXPECTED_DOCUMENT_NAMESPACES.each_key do |version|
84
+ assert_path_exists Brot::Schema.bundled_xsd_path(version)
85
+ assert_predicate document(version:).validate, :valid?
86
+ end
87
+ end
88
+
89
+ def test_schema_validate_infers_the_version_from_the_xml_namespace
90
+ assert_predicate Brot::Schema.validate(document.to_xml(pretty: false)), :valid?
91
+ end
92
+
93
+ def test_validate_bang_returns_a_valid_result_for_documents_and_raw_xml
94
+ assert_predicate document.validate!, :valid?
95
+ assert_predicate Brot::Schema.validate!(document.to_xml(pretty: false)), :valid?
96
+ end
97
+
98
+ def test_rejects_an_invalid_iban
99
+ error = assert_raises(Brot::ValidationError) { invalid_document }
100
+
101
+ assert_equal 'iban is invalid', error.message
102
+ end
103
+
104
+ def test_rejects_an_unsupported_version
105
+ error = assert_raises(Brot::ValidationError) { document(version: :'pain.001.999.99') }
106
+
107
+ assert_equal 'version must be one of pain.001.001.12, pain.001.003.03', error.message
108
+ end
109
+
110
+ private
111
+
112
+ def assert_for_each_version(xpath, expected)
113
+ EXPECTED_DOCUMENT_NAMESPACES.each_key { |version| assert_xpath(version, xpath, expected) }
114
+ end
115
+
116
+ def assert_xpath(version, xpath, expected)
117
+ assert_equal expected,
118
+ parsed_document(version).at_xpath(xpath, ns(version)).content
119
+ end
120
+
121
+ def document(version: Brot::PainVersion::PAIN_001_003_03, **overrides)
122
+ attributes = DOCUMENT_ATTRIBUTES.merge(transfers: [transfer(**overrides.slice(:creditor_bic))], version:)
123
+ attributes[:debtor_bic] = overrides[:debtor_bic] if overrides.key?(:debtor_bic)
124
+ Brot::Document.new(**attributes)
125
+ end
126
+
127
+ def invalid_document = Brot::Document.new(**DOCUMENT_ATTRIBUTES, transfers: [transfer], debtor_iban: 'INVALID')
128
+
129
+ def parsed_document(version)
130
+ @parsed_documents ||= {}
131
+ @parsed_documents[version] ||= Nokogiri::XML(document(version:).to_xml)
132
+ end
133
+
134
+ def transfer(**overrides) = Brot::Transfer.new(**TRANSFER_ATTRIBUTES, **overrides)
135
+
136
+ def ns(version) = { 'ns' => EXPECTED_DOCUMENT_NAMESPACES.fetch(version) }
137
+ end
@@ -0,0 +1,474 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Version gemäß DFÜ-Abkommen Anlage 3, Version 2.7, gültig ab November 2013 mit Umsetzung von IBAN Only gemäß EPC SCT 7.0, zudem Erweiterung Service Level auf Externe Codeliste-->
3
+ <!-- Mit XMLSpy v2008 am 29.11.2012 von der SIZ GmbH bearbeitet -->
4
+ <xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03" elementFormDefault="qualified">
5
+ <xs:element name="Document" type="Document"/>
6
+ <xs:complexType name="AccountIdentificationSEPA">
7
+ <xs:sequence>
8
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
9
+ </xs:sequence>
10
+ </xs:complexType>
11
+ <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
12
+ <xs:restriction base="xs:decimal">
13
+ <xs:minInclusive value="0.01"/>
14
+ <xs:maxInclusive value="999999999.99"/>
15
+ <xs:fractionDigits value="2"/>
16
+ <xs:totalDigits value="11"/>
17
+ </xs:restriction>
18
+ </xs:simpleType>
19
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
20
+ <xs:restriction base="xs:string">
21
+ <xs:pattern value="[A-Z]{3,3}"/>
22
+ </xs:restriction>
23
+ </xs:simpleType>
24
+ <xs:complexType name="ActiveOrHistoricCurrencyAndAmountSEPA">
25
+ <xs:simpleContent>
26
+ <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
27
+ <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCodeEUR" use="required"/>
28
+ </xs:extension>
29
+ </xs:simpleContent>
30
+ </xs:complexType>
31
+ <xs:simpleType name="ActiveOrHistoricCurrencyCodeEUR">
32
+ <xs:restriction base="xs:string">
33
+ <xs:enumeration value="EUR"/>
34
+ </xs:restriction>
35
+ </xs:simpleType>
36
+ <xs:complexType name="AmountTypeSEPA">
37
+ <xs:sequence>
38
+ <xs:element name="InstdAmt" type="ActiveOrHistoricCurrencyAndAmountSEPA"/>
39
+ </xs:sequence>
40
+ </xs:complexType>
41
+ <xs:simpleType name="AnyBICIdentifier">
42
+ <xs:restriction base="xs:string">
43
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
44
+ </xs:restriction>
45
+ </xs:simpleType>
46
+ <xs:simpleType name="BICIdentifier">
47
+ <xs:restriction base="xs:string">
48
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
49
+ </xs:restriction>
50
+ </xs:simpleType>
51
+ <xs:simpleType name="BatchBookingIndicator">
52
+ <xs:restriction base="xs:boolean"/>
53
+ </xs:simpleType>
54
+ <xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA1">
55
+ <xs:sequence>
56
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA1"/>
57
+ </xs:sequence>
58
+ </xs:complexType>
59
+ <xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA3">
60
+ <xs:sequence>
61
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA3"/>
62
+ </xs:sequence>
63
+ </xs:complexType>
64
+ <xs:complexType name="CashAccountSEPA1">
65
+ <xs:sequence>
66
+ <xs:element name="Id" type="AccountIdentificationSEPA"/>
67
+ <xs:element name="Ccy" type="ActiveOrHistoricCurrencyCode" minOccurs="0"/>
68
+ </xs:sequence>
69
+ </xs:complexType>
70
+ <xs:complexType name="CashAccountSEPA2">
71
+ <xs:sequence>
72
+ <xs:element name="Id" type="AccountIdentificationSEPA"/>
73
+ </xs:sequence>
74
+ </xs:complexType>
75
+ <xs:complexType name="CategoryPurposeSEPA">
76
+ <xs:sequence>
77
+ <xs:element name="Cd" type="ExternalCategoryPurpose1Code"/>
78
+ </xs:sequence>
79
+ </xs:complexType>
80
+ <xs:simpleType name="ChargeBearerTypeSEPACode">
81
+ <xs:restriction base="xs:string">
82
+ <xs:enumeration value="SLEV"/>
83
+ </xs:restriction>
84
+ </xs:simpleType>
85
+ <xs:simpleType name="CountryCode">
86
+ <xs:restriction base="xs:string">
87
+ <xs:pattern value="[A-Z]{2,2}"/>
88
+ </xs:restriction>
89
+ </xs:simpleType>
90
+ <xs:complexType name="CreditTransferTransactionInformationSCT">
91
+ <xs:sequence>
92
+ <xs:element name="PmtId" type="PaymentIdentificationSEPA"/>
93
+ <xs:element name="PmtTpInf" type="PaymentTypeInformationSCT2" minOccurs="0">
94
+ <xs:annotation>
95
+ <xs:documentation>If used, it is recommended to be used at ‘Payment Information’ level and not at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
96
+ </xs:annotation>
97
+ </xs:element>
98
+ <xs:element name="Amt" type="AmountTypeSEPA"/>
99
+ <xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
100
+ <xs:annotation>
101
+ <xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
102
+ </xs:annotation>
103
+ </xs:element>
104
+ <xs:element name="UltmtDbtr" type="PartyIdentificationSEPA1" minOccurs="0">
105
+ <xs:annotation>
106
+ <xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
107
+ </xs:annotation>
108
+ </xs:element>
109
+ <xs:element name="CdtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA1" minOccurs="0"/>
110
+ <xs:element name="Cdtr" type="PartyIdentificationSEPA2"/>
111
+ <xs:element name="CdtrAcct" type="CashAccountSEPA2"/>
112
+ <xs:element name="UltmtCdtr" type="PartyIdentificationSEPA1" minOccurs="0"/>
113
+ <xs:element name="Purp" type="PurposeSEPA" minOccurs="0"/>
114
+ <xs:element name="RmtInf" type="RemittanceInformationSEPA1Choice" minOccurs="0"/>
115
+ </xs:sequence>
116
+ </xs:complexType>
117
+ <xs:complexType name="CreditorReferenceInformationSEPA1">
118
+ <xs:sequence>
119
+ <xs:element name="Tp" type="CreditorReferenceTypeSEPA"/>
120
+ <xs:element name="Ref" type="Max35Text">
121
+ <xs:annotation>
122
+ <xs:documentation>If a Creditor Reference contains a check digit, the receiving bank is not required to validate this.
123
+ If the receiving bank validates the check digit and if this validation fails, the bank may continue its processing and send the transaction to the next party in the chain.
124
+ RF Creditor Reference may be used (ISO 11649).</xs:documentation>
125
+ </xs:annotation>
126
+ </xs:element>
127
+ </xs:sequence>
128
+ </xs:complexType>
129
+ <xs:complexType name="CreditorReferenceTypeSEPA">
130
+ <xs:sequence>
131
+ <xs:element name="CdOrPrtry" type="CreditorReferenceTypeCodeSEPA"/>
132
+ <xs:element name="Issr" type="Max35Text" minOccurs="0"/>
133
+ </xs:sequence>
134
+ </xs:complexType>
135
+ <xs:complexType name="CreditorReferenceTypeCodeSEPA">
136
+ <xs:sequence>
137
+ <xs:element name="Cd" type="DocumentType3CodeSEPA"/>
138
+ </xs:sequence>
139
+ </xs:complexType>
140
+ <xs:complexType name="CustomerCreditTransferInitiationV03">
141
+ <xs:sequence>
142
+ <xs:element name="GrpHdr" type="GroupHeaderSCT"/>
143
+ <xs:element name="PmtInf" type="PaymentInstructionInformationSCT" maxOccurs="unbounded"/>
144
+ </xs:sequence>
145
+ </xs:complexType>
146
+ <xs:complexType name="DateAndPlaceOfBirth">
147
+ <xs:sequence>
148
+ <xs:element name="BirthDt" type="ISODate"/>
149
+ <xs:element name="PrvcOfBirth" type="Max35Text" minOccurs="0"/>
150
+ <xs:element name="CityOfBirth" type="Max35Text"/>
151
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
152
+ </xs:sequence>
153
+ </xs:complexType>
154
+ <xs:simpleType name="DecimalNumber">
155
+ <xs:restriction base="xs:decimal">
156
+ <xs:fractionDigits value="17"/>
157
+ <xs:totalDigits value="18"/>
158
+ </xs:restriction>
159
+ </xs:simpleType>
160
+ <xs:complexType name="Document">
161
+ <xs:sequence>
162
+ <xs:element name="CstmrCdtTrfInitn" type="CustomerCreditTransferInitiationV03"/>
163
+ </xs:sequence>
164
+ </xs:complexType>
165
+ <xs:simpleType name="DocumentType3CodeSEPA">
166
+ <xs:restriction base="xs:string">
167
+ <xs:enumeration value="SCOR"/>
168
+ </xs:restriction>
169
+ </xs:simpleType>
170
+ <xs:simpleType name="ExternalCategoryPurpose1Code">
171
+ <xs:restriction base="xs:string">
172
+ <xs:minLength value="1"/>
173
+ <xs:maxLength value="4"/>
174
+ </xs:restriction>
175
+ </xs:simpleType>
176
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
177
+ <xs:restriction base="xs:string">
178
+ <xs:minLength value="1"/>
179
+ <xs:maxLength value="4"/>
180
+ </xs:restriction>
181
+ </xs:simpleType>
182
+ <xs:simpleType name="ExternalPersonIdentification1Code">
183
+ <xs:restriction base="xs:string">
184
+ <xs:minLength value="1"/>
185
+ <xs:maxLength value="4"/>
186
+ </xs:restriction>
187
+ </xs:simpleType>
188
+ <xs:simpleType name="ExternalPurpose1Code">
189
+ <xs:restriction base="xs:string">
190
+ <xs:minLength value="1"/>
191
+ <xs:maxLength value="4"/>
192
+ </xs:restriction>
193
+ </xs:simpleType>
194
+ <xs:simpleType name="ExternalServiceLevel1Code">
195
+ <xs:restriction base="xs:string">
196
+ <xs:minLength value="1"/>
197
+ <xs:maxLength value="4"/>
198
+ </xs:restriction>
199
+ </xs:simpleType>
200
+ <xs:complexType name="FinancialInstitutionIdentificationSEPA1">
201
+ <xs:sequence>
202
+ <xs:element name="BIC" type="BICIdentifier"/>
203
+ </xs:sequence>
204
+ </xs:complexType>
205
+ <xs:complexType name="FinancialInstitutionIdentificationSEPA3">
206
+ <xs:sequence>
207
+ <xs:choice>
208
+ <xs:element name="BIC" type="BICIdentifier"/>
209
+ <xs:element name="Othr" type="OthrIdentification"/>
210
+ </xs:choice>
211
+ </xs:sequence>
212
+ </xs:complexType>
213
+ <xs:complexType name="OthrIdentification">
214
+ <xs:sequence>
215
+ <xs:element name="Id" type="OthrIdentificationCode"/>
216
+ </xs:sequence>
217
+ </xs:complexType>
218
+ <xs:simpleType name="OthrIdentificationCode">
219
+ <xs:restriction base="xs:string">
220
+ <xs:enumeration value="NOTPROVIDED"/>
221
+ </xs:restriction>
222
+ </xs:simpleType>
223
+ <xs:complexType name="GenericOrganisationIdentification1">
224
+ <xs:sequence>
225
+ <xs:element name="Id" type="Max35Text"/>
226
+ <xs:element name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice" minOccurs="0"/>
227
+ <xs:element name="Issr" type="Max35Text" minOccurs="0"/>
228
+ </xs:sequence>
229
+ </xs:complexType>
230
+ <xs:complexType name="GenericPersonIdentification1">
231
+ <xs:sequence>
232
+ <xs:element name="Id" type="Max35Text"/>
233
+ <xs:element name="SchmeNm" type="PersonIdentificationSchemeName1Choice" minOccurs="0"/>
234
+ <xs:element name="Issr" type="Max35Text" minOccurs="0"/>
235
+ </xs:sequence>
236
+ </xs:complexType>
237
+ <xs:complexType name="GroupHeaderSCT">
238
+ <xs:sequence>
239
+ <xs:element name="MsgId" type="RestrictedIdentificationSEPA1"/>
240
+ <xs:element name="CreDtTm" type="ISODateTime"/>
241
+ <xs:element name="NbOfTxs" type="Max15NumericText"/>
242
+ <xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
243
+ <xs:element name="InitgPty" type="PartyIdentificationSEPA1"/>
244
+ </xs:sequence>
245
+ </xs:complexType>
246
+ <xs:simpleType name="IBAN2007Identifier">
247
+ <xs:restriction base="xs:string">
248
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
249
+ </xs:restriction>
250
+ </xs:simpleType>
251
+ <xs:simpleType name="ISODate">
252
+ <xs:restriction base="xs:date"/>
253
+ </xs:simpleType>
254
+ <xs:simpleType name="ISODateTime">
255
+ <xs:restriction base="xs:dateTime"/>
256
+ </xs:simpleType>
257
+ <xs:simpleType name="Max140Text">
258
+ <xs:restriction base="xs:string">
259
+ <xs:minLength value="1"/>
260
+ <xs:maxLength value="140"/>
261
+ </xs:restriction>
262
+ </xs:simpleType>
263
+ <xs:simpleType name="Max15NumericText">
264
+ <xs:restriction base="xs:string">
265
+ <xs:pattern value="[0-9]{1,15}"/>
266
+ </xs:restriction>
267
+ </xs:simpleType>
268
+ <xs:simpleType name="Max35Text">
269
+ <xs:restriction base="xs:string">
270
+ <xs:minLength value="1"/>
271
+ <xs:maxLength value="35"/>
272
+ </xs:restriction>
273
+ </xs:simpleType>
274
+ <xs:simpleType name="Max70Text">
275
+ <xs:restriction base="xs:string">
276
+ <xs:minLength value="1"/>
277
+ <xs:maxLength value="70"/>
278
+ </xs:restriction>
279
+ </xs:simpleType>
280
+ <xs:complexType name="OrganisationIdentificationSEPAChoice">
281
+ <xs:sequence>
282
+ <xs:choice>
283
+ <xs:element name="BICOrBEI" type="AnyBICIdentifier"/>
284
+ <xs:element name="Othr" type="GenericOrganisationIdentification1"/>
285
+ </xs:choice>
286
+ </xs:sequence>
287
+ </xs:complexType>
288
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
289
+ <xs:sequence>
290
+ <xs:choice>
291
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
292
+ <xs:element name="Prtry" type="Max35Text"/>
293
+ </xs:choice>
294
+ </xs:sequence>
295
+ </xs:complexType>
296
+ <xs:complexType name="PartySEPAChoice">
297
+ <xs:sequence>
298
+ <xs:choice>
299
+ <xs:element name="OrgId" type="OrganisationIdentificationSEPAChoice">
300
+ <xs:annotation>
301
+ <xs:documentation>Either ‘BIC or BEI’ or one
302
+ occurrence of ‘Other’ is allowed.</xs:documentation>
303
+ </xs:annotation>
304
+ </xs:element>
305
+ <xs:element name="PrvtId" type="PersonIdentificationSEPA1Choice">
306
+ <xs:annotation>
307
+ <xs:documentation>Either ‘Date and Place of Birth’ or one occurrence of ‘Other’ is allowed.</xs:documentation>
308
+ </xs:annotation>
309
+ </xs:element>
310
+ </xs:choice>
311
+ </xs:sequence>
312
+ </xs:complexType>
313
+ <xs:complexType name="PartyIdentificationSEPA1">
314
+ <xs:sequence>
315
+ <xs:element name="Nm" type="Max70Text" minOccurs="0">
316
+ <xs:annotation>
317
+ <xs:documentation>‘Name’ is limited to 70 characters
318
+ in length.</xs:documentation>
319
+ </xs:annotation>
320
+ </xs:element>
321
+ <xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
322
+ </xs:sequence>
323
+ </xs:complexType>
324
+ <xs:complexType name="PartyIdentificationSEPA2">
325
+ <xs:sequence>
326
+ <xs:element name="Nm" type="Max70Text">
327
+ <xs:annotation>
328
+ <xs:documentation>‘Name’ is limited to 70 characters
329
+ in length.</xs:documentation>
330
+ </xs:annotation>
331
+ </xs:element>
332
+ <xs:element name="PstlAdr" type="PostalAddressSEPA" minOccurs="0"/>
333
+ <xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
334
+ </xs:sequence>
335
+ </xs:complexType>
336
+ <xs:complexType name="PaymentIdentificationSEPA">
337
+ <xs:sequence>
338
+ <xs:element name="InstrId" type="RestrictedIdentificationSEPA1" minOccurs="0"/>
339
+ <xs:element name="EndToEndId" type="RestrictedIdentificationSEPA1"/>
340
+ </xs:sequence>
341
+ </xs:complexType>
342
+ <xs:complexType name="PaymentInstructionInformationSCT">
343
+ <xs:sequence>
344
+ <xs:element name="PmtInfId" type="RestrictedIdentificationSEPA1"/>
345
+ <xs:element name="PmtMtd" type="PaymentMethodSCTCode">
346
+ <xs:annotation>
347
+ <xs:documentation>Only ‘TRF’ is allowed.</xs:documentation>
348
+ </xs:annotation>
349
+ </xs:element>
350
+ <xs:element name="BtchBookg" type="BatchBookingIndicator" minOccurs="0">
351
+ <xs:annotation>
352
+ <xs:documentation>If present and contains ‘true’, batch booking is requested. If present and contains ‘false’, booking per transaction is requested. If element is not present, pre-agreed customer-to-bank conditions apply.</xs:documentation>
353
+ </xs:annotation>
354
+ </xs:element>
355
+ <xs:element name="NbOfTxs" type="Max15NumericText" minOccurs="0"/>
356
+ <xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
357
+ <xs:element name="PmtTpInf" type="PaymentTypeInformationSCT1" minOccurs="0">
358
+ <xs:annotation>
359
+ <xs:documentation>If used, it is recommended to be used only at ‘Payment Information’ level and not at Credit Transfer Transaction Information’ level.
360
+ When Instruction Priority is to be used, ‘Payment Type Information’ must be present at ‘Payment Information’ level. </xs:documentation>
361
+ </xs:annotation>
362
+ </xs:element>
363
+ <xs:element name="ReqdExctnDt" type="ISODate"/>
364
+ <xs:element name="Dbtr" type="PartyIdentificationSEPA2"/>
365
+ <xs:element name="DbtrAcct" type="CashAccountSEPA1"/>
366
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA3"/>
367
+ <xs:element name="UltmtDbtr" type="PartyIdentificationSEPA1" minOccurs="0">
368
+ <xs:annotation>
369
+ <xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
370
+ </xs:annotation>
371
+ </xs:element>
372
+ <xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
373
+ <xs:annotation>
374
+ <xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
375
+ </xs:annotation>
376
+ </xs:element>
377
+ <xs:element name="CdtTrfTxInf" type="CreditTransferTransactionInformationSCT" maxOccurs="unbounded"/>
378
+ </xs:sequence>
379
+ </xs:complexType>
380
+ <xs:simpleType name="PaymentMethodSCTCode">
381
+ <xs:restriction base="xs:string">
382
+ <xs:enumeration value="TRF"/>
383
+ </xs:restriction>
384
+ </xs:simpleType>
385
+ <xs:complexType name="PaymentTypeInformationSCT1">
386
+ <xs:sequence>
387
+ <xs:element name="InstrPrty" type="Priority2Code" minOccurs="0">
388
+ <xs:annotation>
389
+ <xs:documentation>If present, pre-agreed customer-to-bank conditions apply.</xs:documentation>
390
+ </xs:annotation>
391
+ </xs:element>
392
+ <xs:element name="SvcLvl" type="ServiceLevelSEPA"/>
393
+ <xs:element name="CtgyPurp" type="CategoryPurposeSEPA" minOccurs="0">
394
+ <xs:annotation>
395
+ <xs:documentation>Depending on the agreement between the Originator and the Originator Bank, ‘Category Purpose’ may be forwarded to the Beneficiary Bank.</xs:documentation>
396
+ </xs:annotation>
397
+ </xs:element>
398
+ </xs:sequence>
399
+ </xs:complexType>
400
+ <xs:complexType name="PaymentTypeInformationSCT2">
401
+ <xs:sequence>
402
+ <xs:element name="SvcLvl" type="ServiceLevelSEPA"/>
403
+ <xs:element name="CtgyPurp" type="CategoryPurposeSEPA" minOccurs="0">
404
+ <xs:annotation>
405
+ <xs:documentation>Depending on the agreement between the Originator and the Originator Bank, ‘Category Purpose’ may be forwarded to the Beneficiary Bank.</xs:documentation>
406
+ </xs:annotation>
407
+ </xs:element>
408
+ </xs:sequence>
409
+ </xs:complexType>
410
+ <xs:complexType name="PersonIdentificationSEPA1Choice">
411
+ <xs:sequence>
412
+ <xs:choice>
413
+ <xs:element name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
414
+ <xs:element name="Othr" type="GenericPersonIdentification1"/>
415
+ </xs:choice>
416
+ </xs:sequence>
417
+ </xs:complexType>
418
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
419
+ <xs:sequence>
420
+ <xs:choice>
421
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
422
+ <xs:element name="Prtry" type="Max35Text"/>
423
+ </xs:choice>
424
+ </xs:sequence>
425
+ </xs:complexType>
426
+ <xs:complexType name="PostalAddressSEPA">
427
+ <xs:sequence>
428
+ <xs:element name="Ctry" type="CountryCode" minOccurs="0"/>
429
+ <xs:element name="AdrLine" type="Max70Text" minOccurs="0" maxOccurs="2"/>
430
+ </xs:sequence>
431
+ </xs:complexType>
432
+ <xs:simpleType name="Priority2Code">
433
+ <xs:restriction base="xs:string">
434
+ <xs:enumeration value="HIGH"/>
435
+ <xs:enumeration value="NORM"/>
436
+ </xs:restriction>
437
+ </xs:simpleType>
438
+ <xs:complexType name="PurposeSEPA">
439
+ <xs:sequence>
440
+ <xs:element name="Cd" type="ExternalPurpose1Code">
441
+ <xs:annotation>
442
+ <xs:documentation>Only codes from the ISO 20022 ExternalPurposeCode list are allowed.</xs:documentation>
443
+ </xs:annotation>
444
+ </xs:element>
445
+ </xs:sequence>
446
+ </xs:complexType>
447
+ <xs:complexType name="RemittanceInformationSEPA1Choice">
448
+ <xs:sequence>
449
+ <xs:choice>
450
+ <xs:element name="Ustrd" type="Max140Text"/>
451
+ <xs:element name="Strd" type="StructuredRemittanceInformationSEPA1"/>
452
+ </xs:choice>
453
+ </xs:sequence>
454
+ </xs:complexType>
455
+ <xs:complexType name="ServiceLevelSEPA">
456
+ <xs:sequence>
457
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
458
+ </xs:sequence>
459
+ </xs:complexType>
460
+ <xs:complexType name="StructuredRemittanceInformationSEPA1">
461
+ <xs:sequence>
462
+ <xs:element name="CdtrRefInf" type="CreditorReferenceInformationSEPA1" minOccurs="0">
463
+ <xs:annotation>
464
+ <xs:documentation>When present, the receiving bank is not obliged to validate the the reference information. </xs:documentation>
465
+ </xs:annotation>
466
+ </xs:element>
467
+ </xs:sequence>
468
+ </xs:complexType>
469
+ <xs:simpleType name="RestrictedIdentificationSEPA1">
470
+ <xs:restriction base="xs:string">
471
+ <xs:pattern value="([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}"/>
472
+ </xs:restriction>
473
+ </xs:simpleType>
474
+ </xs:schema>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vincent Garrigues
@@ -25,7 +25,7 @@ dependencies:
25
25
  version: '1.18'
26
26
  description: |
27
27
  brot builds SEPA credit transfer XML with Nokogiri::XML::Builder.
28
- The output targets pain.001.001.12 for DATEV-oriented uploads.
28
+ The output targets pain.001.003.03 or pain.001.001.12 for DATEV-oriented uploads.
29
29
  email:
30
30
  - vincent@garriguv.io
31
31
  executables: []
@@ -41,19 +41,21 @@ files:
41
41
  - Rakefile
42
42
  - brot.gemspec
43
43
  - lib/brot.rb
44
- - lib/brot/pain00100112.rb
45
- - lib/brot/pain00100112/account.rb
46
- - lib/brot/pain00100112/document.rb
47
- - lib/brot/pain00100112/schema.rb
48
- - lib/brot/pain00100112/serializer.rb
49
- - lib/brot/pain00100112/serializer_base.rb
50
- - lib/brot/pain00100112/transfer.rb
51
- - lib/brot/pain00100112/utils.rb
44
+ - lib/brot/account.rb
45
+ - lib/brot/document.rb
46
+ - lib/brot/pain_version.rb
47
+ - lib/brot/schema.rb
48
+ - lib/brot/serializer_base.rb
49
+ - lib/brot/serializers/pain00100112.rb
50
+ - lib/brot/serializers/pain00100303.rb
51
+ - lib/brot/transfer.rb
52
+ - lib/brot/utils.rb
52
53
  - lib/brot/version.rb
53
54
  - test/brot_test.rb
54
- - test/pain00100112_document_test.rb
55
+ - test/document_test.rb
55
56
  - test/test_helper.rb
56
57
  - xsd/pain.001.001.12.xsd
58
+ - xsd/pain.001.003.03.xsd
57
59
  homepage: https://github.com/garriguv/brot
58
60
  licenses:
59
61
  - MIT