Mapping-Versionen
Wie die Feldnamen eines ERP zu unserer Rechnung werden und wie sich Versionen ändern.
- In der Sandbox
In einfachen Worten
Ein Mapping übersetzt die Feldnamen eines ERP in unser Rechnungsmodell; so kann ein Fehler das Feld im eigenen Export des Kunden nennen. Ändern sich die Feldnamen eines Kunden, fügen wir eine neue Version hinzu und behalten die alte, damit wir zurückwechseln können. Business Central und SAP Business One sind gemappt, jeweils nach der veröffentlichten Struktur des ERP und noch nicht nach dem eigenen Export eines Kunden.
Ein Mapping macht aus einem ERP-Export unsere kanonische Rechnung. Ändern sich die Feldnamen eines Kunden, fügen wir eine neue Version hinzu und setzen den Live-Zeiger um. Die alte Version bleibt, deshalb kann der Zeiger zurückgesetzt werden.
Was es heute gibt
Zwei ERP-Systeme sind gemappt: Business Central (die Verkaufsrechnung der API v2.0) und SAP Business One (eine Rechnung oder Gutschrift, so wie der Service Layer sie liefert). Jedes hat eine Live-Version, und ältere Versionen bleiben.
Hinweis
Beide Mappings wurden nach der veröffentlichten Struktur des ERP geschrieben und mit erfundenen Exporten getestet, weil noch kein Export eines Kunden vorliegt. Ein Kunde, dessen Export andere Namen verwendet, bekommt eine neue Version. Nichts hier verlangt vom Kunden, das ERP zu ändern.
Ein Export geht an POST /validate oder POST /invoices, mit connector und export statt document.
Einen Export senden
POST /validate nimmt connector (business-central oder sap-b1) und export (das Exportobjekt) statt document an; POST /invoices nimmt dieselben beiden Felder an. Felder, die das Mapping nicht kennt, werden ignoriert. Der Bericht gibt in mapping_version an, welche Version gelaufen ist. Die Anfrage ist validate-export-ok.json, ein Export mit erfundenen Beteiligten.
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"
}Eine andere Version ausprobieren
mapping_version in der Anfrage wählt eine Version für diesen Aufruf. Der Zeiger bewegt sich nicht. Für eine Version, die es nicht gibt, lautet die Antwort 400. Die Anfrage ist validate-export-bad-version.json, derselbe Export mit "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
}Das Feld im ERP finden
Ein Befund nennt das Feld des ERP, nicht unser kanonisches. Eine Einheit, die das Mapping nicht kennt, liegt bei uns: Wir fügen sie der Einheitentabelle hinzu und erstellen eine neue Version. Die Anfrage ist validate-export-bad-unit.json; ihre Einheit Kiste steht nicht in der Tabelle.
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"
}Fehlende Daten liegen beim Partner. Im zugehörigen Befund ist who_fixes auf erp gesetzt, und er nennt das Feld des ERP, das zu ergänzen ist.
Wie eine Änderung ausgeliefert wird
- Wir kopieren die Live-Version in eine neue Version und ändern sie. Die alte bleibt.
- Wir senden die Beispielexporte des Kunden und setzen dabei
mapping_versionauf die neue Version, während die alte live bleibt. - Wir setzen den Live-Zeiger auf die neue Version um.
- Wenn etwas nicht stimmt, setzen wir den Zeiger zurück.