Inleiding
ORAFIN is de boekhoudkundige dienst van de Vlaamse overheid (Oracle Finance), gebruikt door het Dienstencentrum Boekhouding (DCB) van het Departement Financiën en Begroting. De Skryv-platformconnector maakt het mogelijk om via ORAFIN uitbetalingen te laten uitvoeren, bijvoorbeeld van een premie.
Belangrijk: deze platformconnector is een aanzet, geen kant-en-klare oplossing. Ze levert de bouwstenen (bestanden opbouwen, versturen, ophalen en verwerken), maar elk project bouwt hier zelf een eigen laag bovenop. Bijvoorbeeld om te bepalen wélk dossier op welk moment een uitbetaling nodig heeft, hoe vaak er gecontroleerd wordt op nieuwe bestanden bij ORAFIN, en hoe de eigen dossierstructuur gekoppeld wordt aan de ORAFIN-bestanden. Zie deze pagina dus als startpunt voor een projectspecifieke ORAFIN-connector, niet als een afgewerkt geheel.
Use cases
Een uitbetaling (bijvoorbeeld van een premie) laten uitvoeren via ORAFIN: begunstigden bundelen, een betalingsopdracht genereren en versturen, de aanvaarding ervan opvolgen, en na effectieve uitbetaling de betrokken dossiers hiervan op de hoogte stellen.
Terugvorderingen zijn geen onderdeel van deze platformconnector. Een project dat dit nodig heeft, implementeert dit zelf, in het verlengde van dezelfde bestandsuitwisselingslogica.
Setup
Onboarding
Je kan de connector enkel in gebruik nemen na een uitvoerige onboardingsprocedure bij ORAFIN. Hierbij verkrijg je alle info voor het opzetten van de connectie, en worden de nodige afspraken gemaakt rond de informatie-uitwisseling (o.a. de betekenis van een aantal vrij invulbare velden, zie ‘formuliertemplates’ verderop).
Dependency toevoegen aan pom.xml bestand
Om de connector te kunnen gebruiken, voeg je deze eerst als maven dependency toe aan het pom.xml bestand van je applicatie. Deze haalt de code voor de connector op bij het maken van de build voor je app.
<dependency>
<groupId>com.skryv.backend</groupId>
<artifactId>orafin</artifactId>
<version>${skryv.version}</version>
</dependency>
Communicatie
De communicatie met ORAFIN verloopt niet via REST-calls, maar via een protocol gebaseerd op tekstbestanden (flat files): informatie zit verpakt in regels met een vaste kolombreedte per veld, niet in JSON of XML.
De flow verloopt via drie bestanden:
-
InFile: een opdracht tot uitbetaling, gecodeerd als tekstbestand en geplaatst op de server van ORAFIN. -
OutFile: het resultaat van ORAFIN's controle op die opdracht (aanvaard of niet, per begunstigde). -
BetFile: een bevestiging van ORAFIN dat de effectieve uitbetaling heeft plaatsgevonden.
Deze bestanden bevatten informatie over één of meerdere begunstigden. Je kan dus meerdere uitbetalingen in één bestand bundelen.
De platformconnector maakt hierbij gebruik van twee onafhankelijke, elk apart instelbare mechanismen:
-
Eigen opslag van de bestanden (los van ORAFIN zelf): lokaal op het bestandssysteem (default), of op AWS S3.
-
De effectieve verbinding naar de ORAFIN-server: plain FTP (default) of SFTP met authenticatie via private key.
Let op: de platformconnector levert enkel de functies om bestanden op te bouwen, te versturen en te verwerken. Het periodiek controleren op nieuwe bestanden (scheduling) en het koppelen aan je eigen dossierstructuur bouw je zelf, als onderdeel van je projectspecifieke uitbreiding.
Applicatie eigenschappen
Vul onderstaande applicatie eigenschappen in om binnen je project gebruik te maken van de connector.
|
Eigenschap |
Default |
Uitleg |
|---|---|---|
|
Opslag (eigen archief van In-/Out-/BetFiles) |
||
|
|
|
|
|
|
|
Basismap (lokaal of S3-prefix). |
|
|
|
Submap voor InFiles. |
|
|
|
Submap voor OutFiles/BetFiles. |
|
|
|
Submap voor succesvol verwerkte bestanden. |
|
|
|
Submap voor bestanden die een verwerkingsfout gaven. |
|
|
|
Enkel relevant bij |
|
|
|
Enkel relevant bij |
|
|
|
Encryptie-algoritme, enkel bij |
|
|
— |
KMS-sleutel-id, enkel bij |
|
Connectie met ORAFIN-service |
||
|
|
|
|
|
|
|
Hostnaam van de ORAFIN-server. |
|
|
|
Poort. |
|
|
|
Gebruikersnaam. |
|
|
- |
Wachtwoord. Enkel relevant bij |
|
|
- |
Optionele proxy (enkel bij |
|
|
|
Proxypoort. |
|
|
|
|
|
|
- |
Pad naar de private key (lokaal bestand, of secret-naam bij |
|
|
- |
Wachtwoord van de private key. |
|
|
|
Basismap op de ORAFIN-server zelf. |
|
|
|
Submap op de ORAFIN-server waar InFiles geplaatst worden. |
|
|
|
Submap op de ORAFIN-server waar OutFiles/BetFiles opgehaald worden. |
Formuliertemplates voor uitwisseling met ORAFIN
Om de connector te kunnen gebruiken, voorzie je in je project twee formuliertemplates (documenten binnen de scope van het dossier). De platformconnector verwacht deze structuur letterlijk. De veldnamen hieronder komen rechtstreeks uit de broncode, dus wijzig ze niet.
Je project kan bijkomende, eigen velden toevoegen aan beide documenten (bv. extra Spare-velden die specifiek met ORAFIN afgesproken zijn voor dat project). De platformconnector negeert onbekende velden gewoon. De opgelijste velden zijn echter degene die de platformcode zelf effectief leest of schrijft, en dus niet vrijblijvend zijn.
Input-document: betalingsregels
Gelezen door prepareOrafinBulkDossiers. Bevat de ruwe betalingsaanvragen vóór ze gebundeld worden.
|
Veld |
Datatype |
Verplicht |
Uitleg |
|---|---|---|---|
|
|
Lijst |
Ja |
Lijst van begunstigden voor dit dossier. Minstens één vereist — een leeg |
|
|
SelectedOption |
Ja |
|
|
|
String |
CV |
Naam van de particulier. Verplicht bij |
|
|
String |
CV |
Rijksregisternummer. Verplicht bij |
|
|
String |
CV |
Naam van de onderneming. Verplicht bij |
|
|
String |
CV |
KBO-nummer. Verplicht bij |
|
|
Number |
Ja |
Uit te betalen bedrag. Dossiers waarvan de som van alle premies niet groter is dan 0, worden genegeerd. |
|
|
String |
Ja |
Rekeningnummer. Numerieke waarden worden automatisch voorafgegaan door |
|
|
Boolean |
Nee |
Indien |
|
|
String |
Nee |
Enkel nodig bij een buitenlandse rekening. Spaties worden automatisch verwijderd. |
|
|
String |
Nee |
Boekhoudkundige sleutel, af te spreken met ORAFIN. |
|
|
String |
Nee |
Aantal dagen uitstel van betaling. |
Trackingdocument: orafin
Dit document wordt door je project zelf aangemaakt/bijgewerkt (via writeOrafinDocument) en vervolgens door de overige functies (createOrafinInFile, processOrafinOutFile, processPayments, enzovoort) gelezen en bijgewerkt. Het bevat twee delen: de dossiers/begunstigden zelf, en een settings-sectie met omgevingsspecifieke standaardwaarden.
Dossiers en begunstigden
|
Veld |
Datatype |
Uitleg |
|---|---|---|
|
|
Lijst |
Eén item per dossier. |
|
|
String |
Dossiernummer/-label. |
|
|
Lijst |
Begunstigden van dit dossier. |
|
|
String |
Unieke id van de betalingsopdracht (gegenereerd door de connector). |
|
|
String |
Rijksregisternummer of KBO-nummer. |
|
|
String |
Naam begunstigde. |
|
|
ChoiceOption |
Overgenomen uit het input-document. |
|
|
Number |
Uit te betalen bedrag. |
|
|
String |
Rekeningnummer. |
|
|
String |
BIC, indien van toepassing. |
|
|
Boolean |
Zie hierboven. |
|
|
String |
Zie hierboven. |
|
|
String |
Zie hierboven. |
|
|
String |
Wordt ingevuld door |
|
|
String |
Wordt ingevuld door |
|
|
ChoiceOption |
Vervolgactie, bepaald via een DMN-beslissingstabel ( |
Settings-sectie
Vaste standaardwaarden, gebruikt bij het opbouwen van de InFile.
|
Veld |
Uitleg |
|---|---|
|
|
Valuta, doorgaans |
|
|
Betalingstermijn, af te spreken met ORAFIN. |
|
|
Bron-identificatie, gebruikt in de InFile-bestandsnaam. |
|
|
Af te spreken met ORAFIN. |
|
|
Vast voorvoegsel voor de gestructureerde mededeling. |
|
|
Af te spreken met ORAFIN. |
|
|
Af te spreken met ORAFIN. |
|
|
Af te spreken met ORAFIN. |
|
|
Standaard boekhoudkundige sleutel, tenzij per begunstigde overschreven. |
|
|
Af te spreken met ORAFIN. |
Scheduler
De platformconnector bevat zelf geen scheduler. Er is geen ingebouwd periodiek mechanisme dat automatisch nieuwe OutFiles/BetFiles bij ORAFIN ophaalt. Dit moet elk project zelf voorzien, want zonder een periodieke check komt er nooit een antwoord van ORAFIN binnen om te verwerken.
Een typische aanpak, als vertrekpunt (geen voorgeschreven implementatie):
-
Een periodieke taak (bv. via Spring's
@Scheduled, met een cron-expressie als applicatie-eigenschap), die op een vast tijdstip:-
OrafinManager.readOrafinOutFiles()aanroept om nieuwe bestanden bij ORAFIN op te halen, lokaal op te slaan, en van de ORAFIN-server te verwijderen. -
de opgehaalde bestandsnamen onderverdeelt op prefix (bv. bestanden die starten met
OUT_AP_INVOICESzijn OutFiles, bestanden die starten metOUT_AP_BETzijn BetFiles).
-
-
Verdere verwerking triggeren per bestand. Bijvoorbeeld door een eigen BPMN-proces te starten met de bestandsnamen als procesvariabele, dat vervolgens
OrafinService.processOrafinOutFile(...)/analyzeBetFile(...)aanroept (rechtstreeks, of via je eigen projectlaag). -
Voorkom overlappende uitvoeringen: als een vorige verwerkingscyclus nog niet afgerond is (bv. een vorig BPMN-proces nog actief), start dan geen nieuwe. Anders loop je het risico dat hetzelfde bestand dubbel verwerkt wordt.
Onderstaand schema illustreert precies dit patroon in de praktijk, gebaseerd op hoe een bestaand project dit heeft aangepakt. Het is geen exacte specificatie van wat de platformconnector zelf doet, en geen verplichte structuur. De concrete keuzes (cron-frequentie, hoe je bestanden aan dossiers koppelt, welk BPMN-proces je opzet) zijn projectspecifiek.
De werking van de scheduler is hier via BPMN-notatie beschreven, maar programmatie en uitvoering gebeuren in de praktijk via een ‘full-code’ Java-extensie.
Het schema onderscheidt twee niveaus:
-
Scope: individueel dossier (bovenaan). Dit toont het uitbetalingsproces van één dossier. Dit proces vult het
ORAFIN-formulier in en wacht daarna passief op berichten, die het ontvangt zodra de scheduler een antwoord van ORAFIN verwerkt heeft. -
Scope: over alle dossiers heen (onderaan, ‘Skryv applicatie’). Dit toont de scheduler, die je zelf opzet (zie hierboven ‘Scheduler (project-verantwoordelijkheid)’). Deze verzamelt 's morgens alle klaarstaande
ORAFIN-formulieren, bundelt ze in éénInFile, en verstuurt die naar ORAFIN. 's Avonds haalt de scheduler deOutFileen deBetFileop, en stuurt telkens een bericht naar alle betrokken dossiers. Cruciaal daarbij zijn de messages die vanuit de scheduler naar de individuele dossiers gestuurd worden. Daarbij heb je nood aan een combinatie van twee unieke ID’s: enerzijds de process business key (unieke ID van het dossier) en anderzijds de payment ID (unieke ID van de betaling). Het is immers mogelijk om binnen één dossier meerdere uitbetalingsverzoeken te voorzien. Deze moeten afzonderlijk aanstuurbaar zijn.
Services en functies
Herinnering: dit zijn de generieke bouwstenen van de platformconnector. Ze verwachten dat elk project zelf instaat voor het ophalen en wegschrijven van het onderliggende Skryv-document (de rawDocumentValue/Map-parameters). De connector doet dit niet zelf. Een project bouwt hier typisch een eigen facade-laag overheen die deze functies aanroept en de documentopslag regelt.
Overzicht
|
Functie |
Retourtype |
Info |
|---|---|---|
|
|
Bundelt begunstigden per dossier tot een uitbetalingsstructuur, op basis van een lijst dossiers met hun betalingsregels. |
|
|
|
Schrijft een lijst gebundelde dossiers ( |
|
|
|
Bouwt de InFile-inhoud op basis van het ORAFIN-document van een dossier. |
|
|
|
Verwerkt een opgehaalde OutFile en werkt de status van elke begunstigde bij. |
|
|
|
Stuurt een bericht naar elk dossier waarvan de uitbetaling geïmporteerd is door ORAFIN. |
|
|
|
Zelfde als hierboven, maar geeft de lijst dossiernummers terug in plaats van zelf te versturen. |
|
|
|
Leest de omschrijving uit een OutFile, zonder deze te verwerken. |
|
|
|
Stuurt een bericht naar elk dossier waarvan de uitbetaling effectief betaald is. |
|
|
|
Zelfde als hierboven, maar geeft de lijst betaalde dossiers terug in plaats van zelf te versturen. |
|
|
|
Leest een BetFile en groepeert de uitgevoerde betalingen per omschrijving. |
|
|
|
Verplaatst een verwerkte BetFile naar de "processed"-map. |
|
|
|
Werkt de begunstigden in het ORAFIN-document bij met de effectief uitgevoerde betalingen. |
|
|
|
Geeft de lijst dossiernummers terug die momenteel in het ORAFIN-document zitten. |
Deze functies zijn rechtstreeks aanroepbaar vanuit Java-code door OrafinService (bean orafinService) te injecteren in je klasse:
@RequiredArgsConstructor
public class MyOwnService {
private final OrafinService orafinService;
}
prepareOrafinBulkDossiers
Java-code
List<OrafinBulkDossier> bulkDossiers = orafinService.prepareOrafinBulkDossiers(prepareRequests);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
List<PrepareOrafinRequest> |
Per dossier: |
Output
Een lijst OrafinBulkDossier, elk met dossierId, dossierLabel, beneficiaries (lijst begunstigden). Dossiers waarvan de som van alle premies niet groter dan 0 is, worden er automatisch uitgefilterd.
Error-handling
Gooit een niet-opvangbare IllegalStateException als een dossier geen enkele begunstigde bevat in zijn betalingsregels-document.
writeOrafinDocument
Java-code
orafinService.writeOrafinDocument(execution);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
VariableScope (bv. |
Verwacht een procesvariabele |
Output
Geen output (void). Zet zelf niets weg in het Skryv-document. Geeft enkel een OrafinDocument-structuur terug die je project vervolgens zelf naar het ORAFIN-document moet schrijven.
createOrafinInFile
Java-code
OrafinFile inFile = orafinService.createOrafinInFile(rawDocumentValue, dossierId);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document van het dossier. |
|
|
String |
Dossier-id. |
Output
Een OrafinFile-object met de opgebouwde I-/L-records voor elke begunstigde met actie ‘include’. Je project stuurt dit zelf door naar OrafinManager.saveOrafinInFile(...) om het effectief te versturen. Dat gebeurt hier niet automatisch.
processOrafinOutFile
Java-code
orafinService.processOrafinOutFile(rawDocumentValue, outFileName);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document van het dossier. |
|
|
String |
Bestandsnaam van de opgehaalde OutFile. |
Output
Geen output (void). Werkt rawDocumentValue zelf bij (status/foutcode/vervolgactie per begunstigde). Je project moet dit bijgewerkte document zelf terugschrijven.
Error-handling
Bij eender welke fout tijdens verwerking wordt de OutFile automatisch verplaatst naar de foutmap. Er wordt geen exceptie doorgegeven, enkel gelogd.
sendImportedMessages / getImportedMessagesReceivers
Java-code
orafinService.sendImportedMessages(rawDocumentValue);
// of, om zelf te versturen in plaats van de connector dit te laten doen:
List<String> ontvangers = orafinService.getImportedMessagesReceivers(rawDocumentValue);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document. |
Output
sendImportedMessages: geen output. Verstuurt zelf een bericht met vaste naam (niet configureerbaar) naar elk dossier waarvan de import volledig is en waarvoor nog geen bericht verstuurd werd.
getImportedMessagesReceivers: geeft in plaats daarvan de lijst dossiernummers terug, zodat je project zelf bepaalt hoe/wanneer het bericht verstuurd wordt.
analyzeOutFile
Java-code
String omschrijving = orafinService.analyzeOutFile(filename);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
String |
Bestandsnaam van de op te halen OutFile. |
Output
De omschrijving uit de eerste regel van de OutFile. Puur om snel te kunnen inspecteren zonder het bestand effectief te verwerken.
sendPaidMessages / getPaidMessagesReceivers
Java-code
orafinService.sendPaidMessages(rawDocumentValue, dossierId);
// of:
List<MessagePaidDossier> betaaldeDossiers = orafinService.getPaidMessagesReceivers(rawDocumentValue, dossierId);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document. |
|
|
String |
Dossier-id, wordt meegegeven in het bericht. |
Output
Analoog aan de Imported-versie hierboven, maar voor de effectieve uitbetaling: vast berichtnaam-patroon, of een lijst MessagePaidDossier (met dossierLabel, paymentDate, mbId) om zelf te versturen.
analyzeBetFile
Java-code
List<PaymentsWithDescription> payments = orafinService.analyzeBetFile(filename);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
String |
Bestandsnaam van de te analyseren BetFile. |
Output
Een lijst, gegroepeerd per omschrijving, van uitgevoerde betalingen (invoiceNumber, paymentDate, paymentAmount).
moveBetToProcessed
Java-code
orafinService.moveBetToProcessed(filename);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
String |
Bestandsnaam van de BetFile die naar de "processed"-map verplaatst moet worden. |
Output
Geen output (void). Verplaatst het bestand naar de ‘processed’-map.
processPayments
Java-code
orafinService.processPayments(rawDocumentValue, payments);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document. |
|
|
List<ExecutedPayment> |
Resultaat van |
Output
Geen output (void). Werkt rawDocumentValue zelf bij met de betaaldatum per begunstigde. Je project schrijft dit bijgewerkte document zelf terug.
getListOfCurrentDossiers
Java-code
List<String> dossiernummers = orafinService.getListOfCurrentDossiers(rawDocumentValue);
Input
|
Inputparameters |
Data type |
Uitleg |
|---|---|---|
|
|
Map |
Ruwe inhoud van het ORAFIN-document. |
Output
Lijst van dossiernummers die momenteel in het ORAFIN-document zitten.