Web API - dávkové/transakční zpracování
Web API podporuje dávkové/transakční zpracování, tj. je možné spojit několik operací/požadavků do jedné dávky a zajistit, že všechny operace budou provedeny jako celek nebo se neprovede žádná z nich. V této kapitole naleznete informace o tom, jakým způsobem požadavky posílané prostřednictvím Web API slučovat do transakcí.
Transakční zpracování je implementováno obdobně jako rozšířené dotazování - tj. formou zasílání JSON objektu v těle POST požadavku.
Obecný zdroj pro dávkové zpracování používá název batch (tj. /{spojení}/batch). Jednotlivé operace jsou obsažené v JSON objektu v poli items.
{
"items": Array<BatchItem>
}
Každá operace (BatchItem) má následující strukturu:
{
"type": string,
"id": string,
"data": any,
"allow_expr": boolean
}
Podporované vlastnosti:
| Vlastnost | Popis |
|---|---|
| type | Typ operace. |
| ID | Unikátní identifikátor operace v rámci jedné dávky. Nesmí začínat číslicí. |
| data | Konkrétní obsah operace (závisí na typu). |
| allow_expr | Příznak, zda je v datech operace (vlastnost data) povoleno používat výrazy. Nepovinná vlastnost, výchozí hodnota je false. |
V současné době jsou podporovány operace create (vytvoření business objektu), update (aktualizace) a delete (smazání). Jednotlivé typy se od sebe liší podporovanými vlastnostmi v rámci deklarace vlastnosti data.
"data": {
"class_id": "accounts",
"object_data": {
"name": "acc 1",
"code": "009"
},
"query": {
"select": ["id", "code", "name"]
},
"with-softvalidation": false,
"strictdataprotection": false
}
}
Podporované vlastnosti:
| Vlastnost | Popis |
|---|---|
| class_id | ID třídy vytvářeného business objektu. |
| object_data | Specifikace vytvářeného business objektu. |
| query |
Seznam polí z vytvořeného business objektu, která se mají vrátit v odpovědi. Nepovinná vlastnost. Výchozí hodnota je ["id"] - viz poznámka k operaci create v níže uvedeném ilustračním příkladu. |
| with-softvalidation |
Příznak, zda se má před uložením vytvářeného objektu provést softvalidace. Nepovinná vlastnost. Výchozí hodnota je true. |
| strictdataprotection |
Určuje, zda se při pokusu o vytvoření BO zohledňuje přístup k chráněným položkám v rámci definic ochrany dat. Nepovinná vlastnost. Výchozí hodnota je true. Viz také Změny ve vytváření a aktualizaci BO v kapitole Web API a ochrana dat. |
"data": {
"class_id": "accounts",
"obj_id": "1J50000101",
"object_data": {
"name": "acc 1"
},
"query": {
"select": ["id", "code", "name"]
},
"with-softvalidation": false,
"strictdataprotection": false
}
}
Podporované vlastnosti:
| Vlastnost | Popis |
|---|---|
| class_id | ID třídy aktualizovaného business objektu. |
| obj_id | ID aktualizovaného business objektu z uvedené třídy. |
| object_data | Specifikace požadovaných změn business objektu. |
| query |
Seznam polí z aktualizovaného business objektu, která se mají vrátit v odpovědi. Nepovinná vlastnost. Výchozí hodnota je ["id"]. |
| with-softvalidation |
Příznak, zda se má před uložením změn provést softvalidace. Nepovinná vlastnost. Výchozí hodnota je true. |
| strictdataprotection |
Určuje, zda se při pokusu o aktualizaci BO zohledňuje přístup k chráněným položkám v rámci definic ochrany dat. Nepovinná vlastnost. Výchozí hodnota je true. Viz také Změny ve vytváření a aktualizaci BO v kapitole Web API a ochrana dat. |
"data": {
"class_id": "accounts",
"obj_id": "1J50000101"
}
Podporované vlastnosti:
| Vlastnost | Popis |
|---|---|
| class_id | ID třídy aktualizovaného business objektu. |
| obj_id | ID aktualizovaného business objektu z uvedené třídy. |
Výsledkem zpracování je opět JSON objekt v následujícím tvaru:
{
"items": Array<BatchItemResult>
}
Každý BatchItemResult má následující strukturu:
{
"id": string,
"data": any
}
Podporované vlastnosti:
| Vlastnost | Popis |
|---|---|
| id | Jednoznačný identifikátor provedené operace. |
| data |
Požadovaný výsledek operace. Standardně obsahuje pouze ID vytvořeného / aktualizovaného / smazaného business objektu, Pro operace typu create nebo update je možné množinu vrácených položek definovat pomocí vlastnosti query ve vstupním JSON objektu. |
Při deklarování vlastností object_data, class_id a obj_id je možné používat zástupné výrazy, které jsou v rámci dávkového zpracování dynamicky nahrazovány hodnotami z předchozích operací. Platí:
- Používání výrazů nesmí být pro danou operaci zakázáno nastavením vlastnosti allow_expr na hodnotu true.
- Položka používající výraz musí být typu řetězec (string).
- Definice musí být ve formátu "${<výraz>}".
- Je možné se odkazovat pouze na proměnné z předchozích operací, a to pomocí jejich ID.
- Od verze 12.1 může být vyhodnocovaný výraz použitý i ve vnořených JSON objektech nebo polích (na libovolné úrovni vnoření). Viz ilustrační příklad 2 níže.
Mějme dvě operace, jejichž ID jsou "a" a "b".
Pokud chceme v operaci "b" dosadit do určité položky hodnotu z předchozí operace "a" (např. v rámci vlastnosti object_data), syntaxe bude následující:
"${a.name + ' nový'}"
Výše uvedené principy si demonstrujeme na příkladu. Ilustrační dávku tvoří trojice operací:
- první operace založí nový záznam v tabulce accounts
- druhá operace nově založený záznam aktualizuje
- třetí operace ho smaže
Díky transakční povaze zpracování bude výsledkem vždy stejný stav jako před zahájením dávky - ať už dávka doběhne v pořádku do konce (provedou se všechny tři operace), nebo kdykoli v průběhu zpracování dojde k chybě (neprovede se ani jedna operace).
Pokud dojde v průběhu zpracování dávky k chybě, výsledkem zpracování je stavový kód 500 Internal Server Error a JSON objekt s bližší specifikací této chyby.
{
"items": [
{
"type": "create",
"id": "a",
"data": {
"class_id": "accounts",
"object_data": {
"name": "acc 1",
"code": "009"
},
"query": {
"select": ["id", "code", "name"]
}
}
},
{
"type": "update",
"id": "b",
"allow_expr": true,
"data": {
"class_id": "accounts",
"obj_id": "${a.id}",
"object_data": {
"name": "${a.name + '0'}",
"code": "${a.code}"
},
"query": {
"select": ["id", "code", "name"]
}
}
},
{
"type": "delete",
"id": "c",
"allow_expr": true,
"data": {
"class_id": "accounts",
"obj_id": "${b.id}"
}
}
]
}
Aby se druhá operace mohla odkazovat na business objekt vytvořený první operací, musí být ve vlastnosti obj_id uveden výraz "${a.id}", kterým vyjadřujeme, že se odkazujeme na operaci s ID = "a", která v předchozím kroku business objekt vytvořila.
V operaci update je následně provedena aktualizace vytvořeného objektu:
- původní hodnota položky name je doplněna sufixem '0'
- do položky code je přiřazena stávající hodnota (přiřazení tedy nezpůsobí žádnou změnu)
Třetí a poslední operace delete se opět odkazuje na předchozí operaci s ID = "b" a business objekt smaže.
Stejně tak by se operace delete mohla odkazovat na operaci s ID = "a", protože ID business objektu se od vytvoření nezměnilo.
{
"items": [
{
"id": "a",
"data": {
"id": "1Z30000101",
"code": "009",
"name": "acc 1"
}
},
{
"id": "b",
"data": {
"id": "1Z30000101",
"code": "009",
"name": "acc 10"
}
},
{
"id": "c",
"data": {
"id": "1Z30000101"
}
}
]
}
Z odpovědi je patrné, že v případě neuvedení nepovinné vlastnosti query (v operaci "a" typu create) je navráceno pouze ID business objektu.
Pro operace typu delete není vlastnost query podporována, tj. bez ohledu na obsah vstupního JSON objektu vrátí operace "c" vždy pouze ID business objektu.
V druhém příkladu si opět ukážeme využití odkazu na objekt vytvořený v předchozí operaci, přičemž tento odkaz bude použitý ve vnořeném objektu (v kolekci řádků).
- první operace (O0) založí skladovou kartu
- druhá operace (O1) založí ceník
- třetí operace (O2) vytvoří definici cen
- čtvrtá operace (O3) vytvoří položku ceníku, ve které nastaví cenu platnou pro danou skladovou kartu a definici cen
Možnost používat odkazy ve vnořených objektech byla nově zavedena ve verzi 21.1.
{
"items": [
{
"type": "create",
"data": {
"class_id": "storecards",
"object_data": {
"category": 0,
"name": "Děrovačka se dvěma otvory",
"foreignname": "",
"code": "DER2",
"plu": null,
"ean": "",
"storecardcategory_id": "1100000101",
"vatrate_id": "02100X0000",
"mainunitcode": "KS"
},
"query": {
"select": [
"id"
]
}
},
"id": "O0",
"allow_expr": true
},
{
"type": "create",
"data": {
"class_id": "pricelists",
"object_data": {
"name": "Ceník z importu",
"code": "IMP"
},
"query": {
"select": [
"id"
]
}
},
"id": "O1",
"allow_expr": true
},
{
"type": "create",
"data": {
"class_id": "pricedefinitions",
"object_data": {
"name": "Cena z importu",
"code": 1,
"pricewithvat": true
},
"query": {
"select": [
"id"
]
}
},
"id": "O2",
"allow_expr": true
},
{
"type": "create",
"data": {
"class_id": "storeprices",
"object_data": {
"storecard_id": "${O0.id}",
"pricelist_id": "${O1.id}",
"pricelistvalidity_id": null,
"deletedfrompricelist": false,
"pricerows": [
{
"amount": 68.97,
"price_id": "${O2.id}",
"qunit": "ks",
"unitrate": 1
}
]
},
"query": {
"select": [
"id"
]
}
},
"id": "O3",
"allow_expr": true
}
]
}
{
"items": [
{
"id": "O0",
"data": {
"id": "7J70000101"
}
},
{
"id": "O1",
"data": {
"id": "1200000101"
}
},
{
"id": "O2",
"data": {
"id": "1200000101"
}
},
{
"id": "O3",
"data": {
"id": "1430000101"
}
}
]
}