Versiuni de mapare
Cum devin numele câmpurilor unui ERP factura noastră și cum se schimbă versiunile.
- În sandbox
În cuvinte simple
O mapare traduce numele câmpurilor unui ERP în modelul nostru de factură; așa poate o eroare să indice câmpul din exportul propriu al clientului. Când se schimbă numele câmpurilor unui client, adăugăm o versiune nouă și o păstrăm pe cea veche, ca să putem reveni. Business Central și SAP Business One sunt mapate, fiecare pornind de la structura publicată a ERP-ului și încă nu de la exportul propriu al unui client.
O mapare transformă exportul unui ERP în factura noastră canonică. Când se schimbă numele câmpurilor unui client, adăugăm o versiune nouă și mutăm pointerul activ. Versiunea veche rămâne, așa că pointerul poate fi mutat înapoi.
Ce există astăzi
Două ERP-uri sunt mapate: Business Central (factura de vânzare din API v2.0) și SAP Business One (o factură sau o notă de credit așa cum le returnează Service Layer). Fiecare are o versiune activă, iar versiunile mai vechi rămân.
Notă
Ambele mapări au fost scrise pornind de la structura publicată a ERP-ului și testate pe exporturi fictive, pentru că nu există încă exportul unui client. Un client al cărui export folosește alte nume primește o versiune nouă. Nimic de aici nu îi cere clientului să modifice ERP-ul.
Un export merge la POST /validate sau la POST /invoices, cu connector și export în locul lui document.
Trimiterea unui export
POST /validate primește connector (business-central sau sap-b1) și export (obiectul exportului) în locul lui document; POST /invoices primește aceleași două câmpuri. Câmpurile pe care maparea nu le cunoaște sunt ignorate. Raportul indică în mapping_version ce versiune a rulat. Cererea este validate-export-ok.json, un export cu părți fictive.
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"
}Încercarea altei versiuni
mapping_version din cerere alege o versiune pentru acel apel. Pointerul nu se mută. O versiune care nu există primește 400. Cererea este validate-export-bad-version.json, același export cu "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
}Găsirea câmpului în ERP
O constatare indică câmpul ERP-ului, nu câmpul nostru canonic. O unitate pe care maparea nu o cunoaște ne revine nouă spre corectare: o adăugăm în tabelul de unități și creăm o versiune nouă. Cererea este validate-export-bad-unit.json, unde Kiste nu este în tabel.
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"
}Datele lipsă revin partenerului spre corectare. Constatarea lor are who_fixes setat la erp și indică câmpul ERP de completat.
Cum se livrează o modificare
- Copiem versiunea activă într-o versiune nouă și o modificăm. Cea veche rămâne.
- Trimitem exporturile exemplu ale clientului cu
mapping_versionsetat la versiunea nouă, în timp ce cea veche rămâne activă. - Mutăm pointerul activ pe versiunea nouă.
- Dacă ceva nu este în regulă, îl mutăm înapoi.