The Payment File the Bank Actually Accepts
Your customer pays vendors from a payment journal, and their bank only accepts ISO 20022 pain.001.001.09 credit transfer files. The bank's validator is merciless: transactions must be grouped into one PmtInf block per debtor account and execution date, the header counts and control sums must add up to the cent, and any character outside the SEPA character set bounces the whole file. You are writing the generator that turns journal fixtures into a file that clears the validator on the first try.
Requirements
The starter ships a table named "SEPA Payment Line" (a TableType = Temporary buffer) — submit it unchanged; the grading tests fill it and pass it to your code.
Create a codeunit named "SEPA Pain001 Export" with one public procedure:
procedure Generate(var SEPAPaymentLine: Record "SEPA Payment Line"; MessageId: Text[35]; CreatedAt: DateTime): TextGenerate reads the payment lines in ascending "Line No." order (the buffer arrives unfiltered with at least one line) and returns the complete pain.001.001.09 document as text.
The document contract
Every element below lives in the namespace urn:iso:std:iso:20022:tech:xsd:pain.001.001.09 — the tests resolve every element namespace-aware, so an element in no (or another) namespace is simply not found.
Document
└── CstmrCdtTrfInitn
├── GrpHdr
│ ├── MsgId MessageId, verbatim
│ ├── CreDtTm CreatedAt in XML format (AL standard format 9)
│ ├── NbOfTxs total number of payment lines
│ └── CtrlSum sum of all line amounts
└── PmtInf one block per group — see grouping rules
├── PmtInfId MessageId + '-' + group number (1-based)
├── PmtMtd always TRF
├── NbOfTxs number of lines in this group
├── CtrlSum sum of the amounts in this group
├── ReqdExctnDt
│ └── Dt the group's execution date as YYYY-MM-DD
├── Dbtr
│ └── Nm debtor name of the group's first line, sanitized, max 70
├── DbtrAcct
│ └── Id
│ └── IBAN the group's debtor IBAN, spaces removed
└── CdtTrfTxInf one per line of the group, ascending Line No.
├── PmtId
│ └── EndToEndId sanitized End-to-End ID, max 35; NOTPROVIDED when blank
├── Amt
│ └── InstdAmt the line amount, with attribute Ccy="EUR"
├── Cdtr
│ └── Nm creditor name, sanitized, max 70
├── CdtrAcct
│ └── Id
│ └── IBAN creditor IBAN, spaces removed
└── RmtInf omit the whole element when Remittance Text is blank
└── Ustrd remittance text, sanitized, max 140Solve it with Pro
You’re reading the opening of the statement. Pro unlocks the whole problem:
- The full statement
- Starter code in the browser editor
- 18 grading tests, run on Business Central 28.5
- 3 hints
- The reference solution
Pro also opens all 92 Pro problems and lifts the daily limits on compile checks and submissions.
Already on Pro? Sign in