Mappingversies
Hoe de veldnamen van een ERP onze factuur worden, en hoe versies veranderen.
- In de sandbox
In gewone woorden
Een mapping vertaalt de veldnamen van één ERP naar ons factuurmodel; zo kan een fout het veld noemen in de eigen export van de eindklant. Als de veldnamen van een eindklant veranderen, voegen we een nieuwe versie toe en bewaren we de oude, zodat we kunnen terugkeren. Business Central en SAP Business One hebben een mapping, elk gemaakt op basis van de gepubliceerde vorm van het ERP en nog niet van een eigen export van een eindklant.
Een mapping zet één ERP-export om in onze canonieke factuur. Als de veldnamen van een eindklant veranderen, voegen we een nieuwe versie toe en verplaatsen we de live pointer. De oude versie blijft bestaan, zodat de pointer terug kan.
Wat er momenteel bestaat
Twee ERP’s hebben een mapping: Business Central (de verkoopfactuur van de API v2.0) en SAP Business One (een factuur of creditnota zoals de Service Layer ze teruggeeft). Elk heeft een live versie, en oudere versies blijven bestaan.
Opmerking
Beide mappings zijn geschreven op basis van de gepubliceerde vorm van het ERP en getest op verzonnen exports, omdat er nog geen export van een eindklant bestaat. Een eindklant van wie de export andere namen gebruikt, krijgt een nieuwe versie. Niets hier vraagt de eindklant om het ERP te wijzigen.
Een export gaat naar POST /validate of POST /invoices, met connector en export in plaats van document.
Een export versturen
POST /validate neemt connector (business-central of sap-b1) en export (het exportobject) aan in plaats van document; POST /invoices neemt dezelfde twee velden aan. Velden die de mapping niet kent, worden genegeerd. Het rapport vermeldt in mapping_version welke versie is uitgevoerd. Het verzoek is validate-export-ok.json, een export met verzonnen partijen.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @validate-export-ok.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("validate-export-ok.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('validate-export-ok.json'),
});
console.log(response.status);
console.log(await response.text());{
"valid": true,
"route": "DE-XRECHNUNG",
"documents": [
{
"sha256": "3e7f648bdc6c6d6f5ad78cd356b39c3020595bb7f0896b78a8510ec6969db317",
"kind": "xrechnung-ubl",
"content_base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgi... (5,900 characters, shortened for these docs)"
}
],
"layers": [
{
"findings": [],
"passed": true,
"layer": "schema"
},
{
"findings": [],
"passed": true,
"layer": "mapping"
},
{
"findings": [],
"passed": true,
"layer": "pre-check"
},
{
"findings": [],
"passed": true,
"layer": "kosit"
}
],
"mapping_version": "v2"
}Een andere versie proberen
mapping_version in het verzoek kiest een versie voor die aanroep. De pointer blijft staan. Een versie die niet bestaat, geeft 400. Het verzoek is validate-export-bad-version.json, dezelfde export met "mapping_version": "v9".
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @validate-export-bad-version.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("validate-export-bad-version.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('validate-export-bad-version.json'),
});
console.log(response.status);
console.log(await response.text());{
"detail": "That mapping version does not exist. The live pointer was left unchanged.",
"type": "https://eurinvoice.com/problems/bad-request",
"title": "The request could not be read",
"status": 400
}Het veld in het ERP vinden
Een bevinding noemt het veld van het ERP, niet ons canonieke veld. Een eenheid die de mapping niet kent, lossen wij op: we voegen ze toe aan de eenhedentabel en brengen een nieuwe versie uit. Het verzoek is validate-export-bad-unit.json, waarin Kiste niet in de tabel staat.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @validate-export-bad-unit.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("validate-export-bad-unit.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('validate-export-bad-unit.json'),
});
console.log(response.status);
console.log(await response.text());{
"valid": false,
"route": "DE-XRECHNUNG",
"layers": [
{
"findings": [],
"passed": true,
"layer": "schema"
},
{
"findings": [
{
"code": "BR-CL-23",
"field": "salesInvoiceLines[0].unitOfMeasureCode",
"fix_hint": "Add the ERP's unit to the client's unit mapping table (for example 'Std.' to HUR).",
"who_fixes": "us",
"source": "mapping",
"message": "A unit of measure on a line is not recognised. We are adding it to your mapping."
}
],
"passed": false,
"layer": "mapping"
},
{
"findings": [],
"passed": true,
"layer": "pre-check"
}
],
"mapping_version": "v2"
}Ontbrekende gegevens moet de partner aanvullen. De bevinding daarvan heeft who_fixes op erp en noemt het ERP-veld dat moet worden ingevuld.
Hoe een wijziging live gaat
- We kopiëren de live versie naar een nieuwe versie en wijzigen die. De oude blijft bestaan.
- We sturen de voorbeeldexports van de eindklant met
mapping_versionop de nieuwe versie, terwijl de oude live blijft. - We zetten de live pointer op de nieuwe versie.
- Als er iets fout is, zetten we hem terug.