Zdroj dynsql ve Web API ABRA Gen
Kromě možnosti pracovat s jednotlivými business objekty je v rozhraní Web API implementováno několik speciálních zdrojů, které slouží ke specifickým účelům. Jedním z nich je zdroj dynsql zpřístupňující dynamická SQL.
Přehled ostatních podporovaných zdrojů naleznete v kapitole Dostupné zdroje.
V současné době je k dispozici následující funkcionalita:
-
Získání seznamu nadefinovaných dynamických SQL - dostupné od ABRA Gen 19.4
GET {{server}}/{{connection}}/dynsql
-
Získání definice konkrétního dynamického SQL - dostupné od ABRA Gen 19.4
GET {{server}}/{{connection}}/dynsql/{{dynsqlid}}
-
Dotazování dynamických SQL - dostupné od ABRA Gen 20.3
POST {{server}}/{{connection}}/dynsql/{{dynsqlid}}/exec
Fragment URL | Popis |
---|---|
{{server}} | Adresa serveru. |
{{connection}} | Název spojení na databázi. |
dynsql | Klíčové slovo označující tento typ zdroje. |
{{dynsqlid}} | ID dynamického SQL ve formátu Packed CLSID, v DynSQL editoru odpovídá hodnotě "ID příkazu" v sekci Dynamické SQL. |
exec | Klíčové slovo určující, že se má provést dotazování dynamického SQL. |
Jednotlivé možnosti si ukážeme na příkladech.
Požadavek:
GET http://localhost:699/demodata/dynsql
Zkrácený výsledek zpracování požadavku:
Status: 200 OK
[
{
"id": "0012IW1H1BH4X24ZFUJKXGA5US",
"name": "INTRASTAT - Přijetí"
},
{
"id": "01B4XCTHYNDL3C5P00CA141B44",
"name": "Země"
},
...
{
"id": "WY15XY0ZAXLO10IB1GALYIP1XK",
"name": "Výběr docházky pro uzávěrku"
}
]
ID je Packed CLSID dynamického SQL, name jeho název.
Packed CLSID dynamického SQL Země je 01B4XCTHYNDL3C5P00CA141B44 - opět zjistíme např. jako hodnotu položky ID příkazu v DynSQL editoru.
Požadavek:
GET http://localhost:699/demodata/dynsql/01B4XCTHYNDL3C5P00CA141B44
Status: 200 OK
{
"id": "01B4XCTHYNDL3C5P00CA141B44",
"name": "Země",
"datasets": [
{
"name": "MAIN",
"sql": "SELECT {FIELDS} FROM\r\n Countries A \r\n {JOIN}\r\n{WHERE}\r\n{ORDERBY}",
"master": "",
"displaylabel": "Země",
"masterfields": "",
"nationallocalization": "",
"fields": [
{
"expression": "A.ObjVersion",
"fieldname": "ObjVersion",
"displaylabel": "Verze objektu",
"packedclsid": "",
"fieldsize": 1,
"datatype": "dtInteger",
"prefixedfield": false,
"nationallocalization": "",
"mastermonikerpclsid": "4J5FINKNYNDL3C5P00CA141B44",
"sqljoinbinding": {
"alias": "",
"fieldname": ""
},
"originalfieldname": ""
},
{
"expression": "A.Hidden",
"fieldname": "Hidden",
"displaylabel": "Skrytý",
"packedclsid": "",
"fieldsize": 1,
"datatype": "dtBoolean",
"prefixedfield": false,
"nationallocalization": "",
"mastermonikerpclsid": "4J5FINKNYNDL3C5P00CA141B44",
"sqljoinbinding": {
"alias": "",
"fieldname": ""
},
"originalfieldname": ""
},
{
"expression": "A.Code",
"fieldname": "Code",
"displaylabel": "Kód",
"packedclsid": "",
"fieldsize": 3,
"datatype": "dtString",
"prefixedfield": false,
"nationallocalization": "",
"mastermonikerpclsid": "4J5FINKNYNDL3C5P00CA141B44",
"sqljoinbinding": {
"alias": "",
"fieldname": ""
},
"originalfieldname": ""
},
....
{
"expression": "C.DocVATRounding AS Currency_DocVATRounding",
"fieldname": "Currency_DocVATRounding",
"displaylabel": "Měna - Zaokrouhlení DPH dokladů",
"packedclsid": "",
"fieldsize": 1,
"datatype": "dtInteger",
"prefixedfield": true,
"nationallocalization": "",
"mastermonikerpclsid": "4R5FINKNYNDL3C5P00CA141B44",
"sqljoinbinding": {
"alias": "A",
"fieldname": "Currency_ID"
},
"originalfieldname": "DocVATRounding"
}
],
"aliases": [
{
"alias": "A",
"clsid": "4J5FINKNYNDL3C5P00CA141B44",
"prefix": "",
"description": "",
"joinsql": ""
},
{
"alias": "C",
"clsid": "4R5FINKNYNDL3C5P00CA141B44",
"prefix": "Currency",
"description": "Měna",
"joinsql": "JOIN Currencies C ON C.ID=A.Currency_ID"
}
]
},
{
"name": "HISTORY",
"sql": "SELECT {FIELDS} FROM\r\n Countries2 A\r\n {JOIN}\r\nWHERE\r\n A.Parent_ID=:ID\r\nORDER BY\r\n DateOfChange$DATE",
"master": "MAIN",
"displaylabel": "Historie",
"masterfields": "ID",
"nationallocalization": "",
"fields": [
{
"expression": "A.ObjVersion",
"fieldname": "ObjVersion",
"displaylabel": "Verze objektu",
"packedclsid": "",
"fieldsize": 1,
"datatype": "dtInteger",
"prefixedfield": false,
"nationallocalization": "",
"mastermonikerpclsid": "5RB1WWGPTEF4RBC5VKEP1Q3GZ0",
"sqljoinbinding": {
"alias": "",
"fieldname": ""
},
"originalfieldname": ""
},
...
{
"expression": "C.ID AS Country_ID",
"fieldname": "Country_ID",
"displaylabel": "Země - Vlastní ID",
"packedclsid": "4J5FINKNYNDL3C5P00CA141B44",
"fieldsize": 10,
"datatype": "dtString",
"prefixedfield": false,
"nationallocalization": "",
"mastermonikerpclsid": "",
"sqljoinbinding": {
"alias": "",
"fieldname": ""
},
"originalfieldname": ""
}
],
"aliases": [
{
"alias": "A",
"clsid": "5RB1WWGPTEF4RBC5VKEP1Q3GZ0",
"prefix": "",
"description": "",
"joinsql": ""
},
{
"alias": "C",
"clsid": "4J5FINKNYNDL3C5P00CA141B44",
"prefix": "Country",
"description": "Země",
"joinsql": "JOIN Countries C ON C.ID=A.Parent_ID"
}
]
}
],
"conditions": [
{
"id": "ID",
"dataset": "MAIN",
"parentid": "",
"params": "CLASSID=4J5FINKNYNDL3C5P00CA141B44\r\n",
"description": "",
"datatype": "ctString",
"specialsubtype": 0,
"caption": "",
"template": "LKR4PB0W0NEL3DW201C0CX3F40",
"alias": "A",
"nationallocalization": ""
},
{
"id": "Code",
"dataset": "MAIN",
"parentid": "",
"params": "",
"description": "",
"datatype": "ctString",
"specialsubtype": 0,
"caption": "",
"template": "2GH0OO0G2NEL3C5V00CA141B44",
"alias": "A",
"nationallocalization": ""
},
...
{
"id": "Hidden",
"dataset": "MAIN",
"parentid": "",
"params": "",
"description": "",
"datatype": "ctString",
"specialsubtype": 0,
"caption": "",
"template": "SGBEBHMDGZE13C5T00CA141B44",
"alias": "A",
"nationallocalization": ""
}
],
"keys": [
{
"id": "Code",
"sql": "A.Code Collate PXW_CSY",
"dataset": "MAIN",
"displaylabel": "Kód",
"nationallocalization": "",
"hidden": false
},
{
"id": "Name",
"sql": "A.Name Collate PXW_CSY",
"dataset": "MAIN",
"displaylabel": "Název",
"nationallocalization": "",
"hidden": false
},
{
"id": "Currency",
"sql": "C.Code Collate PXW_CSY {DIR},A.Currency_ID",
"dataset": "MAIN",
"displaylabel": "Měna",
"nationallocalization": "",
"hidden": false
},
{
"id": "NumCode",
"sql": "A.NumCode",
"dataset": "MAIN",
"displaylabel": "Číselný kód",
"nationallocalization": "",
"hidden": false
}
],
"controller": "00000000000000000000000000",
"system": true,
"nationallocalization": ""
}
Chceme získat kolekci faktur vydaných splňujících určité podmínky. V aplikaci ABRA Gen bychom spustili agendu Faktury vydané, na záložce Omezení podmínky zadali a funkcí Získat záznamy získali požadovanou množinu záznamů. Totéž je od ABRA Gen 20.3 možné realizovat také prostřednictvím Web API.
Budeme potřebovat Packed CLSID dynamického SQL, které nalezneme v DynSQL editoru - naimportujeme repozitoř a v seznamu označíme dynamický SQL příkaz Faktury vydané. Požadovaná hodnota se zobrazí v položce ID příkazu pod seznamem (40SBPEINEFD13ACM03KIU0CLP4).
Požadavek:
POST http://localhost:699/demodata/dynsql/40SBPEINEFD13ACM03KIU0CLP4/exec
Samotný dotaz se předává v těle požadavku v JSON formátu. Může obsahovat následující objekty:
Objekt | Význam | Popis |
---|---|---|
"select" | Seznam položek, které se mají vrátit. | Zadává se jako pole řetězců, v případě jedné hodnoty se nemusí zadávat jako pole. |
"where" | Seznam omezujících podmínek. | Zadává se jako pole objektů, v případě jedné podmínky se nemusí zadávat jako pole. |
"id" | Identifikátor podmínky v definici DynSQL. | Odpovídá hodnotě položky Identifikátor na záložce Podmínky v DynSQL editoru. |
"value" | Hodnota dosazená do podmínky. | V závislosti na definici podmínky v DynSQL se může jednat o jednu hodnotu nebo o pole hodnot, případně nemusí být uvedena. Bližší vysvětlení viz komentář k níže uvedenému vzorovému příkladu. |
"flags" | Volitelné pole textových hodnot, kterými je možné vyhodnocování podmínky ovlivnit. |
Některé flagy jsou obecné, některé mají význam jen pro některé typy podmínek:
|
"orderby" | Seznam klíčů, podle kterých se výsledek seřadí. |
Zadává se jako pole objektů, v případě jedné hodnoty se nemusí zadávat jako pole. Může obsahovat objekty:
|
"datasets" | Pole podřízených datasetů, které se připojí k výstupu. | Zadává se jako pole objektů, které můžou obsahovat “select”, “where” a “orderby” popsané výše. Jejich možné použití záleží na tom, jestli jsou podmínky nebo třídící klíče pro podřízený dataset definované. |
Tělo požadavku:
{
"select": ["ID", "DocQueue_Code", "Period_Code", "OrdNumber", "NotPaidAmount", "DocDate$DATE"],
"where" : [
{
"id": "Firm_ID",
"value": ["J000000101","7000000101","2000000101"]
},
{
"id": "SimplifiedVATDocument",
"value": true
},
{
"id": "TradeType",
"value": "3;9"
},
{
"id": "Rows",
"flags": ["WithDocumentsWithoutRows"]
},
{
"id": "IntrastatCompleteKind",
"value": "0"
},
{
"id": "DocDate",
"value": ["2020-11-14T23:00:00.000Z","2020-11-14T12:00:00.000Z"]
},
{
"id": "description",
"value": "*hello*",
"flags": ["CaseInsensitive"]
},
{
"id": "OrdNumber",
"value": [3,5]
},
{
"ID": "ESLCompleteKind"
}
],
"orderby" : [
{
"id": "DocDate",
"ordering": "desc"
},
{
"id": "OrdNumber"
}
],
"datasets": [
{
"name": "batches",
"select": ["PosIndex", "qunit", "unitrate"]
},
{
"name": "vatrates",
"select": ["VRVATUsageRowsCount", "Name"]
}
]
}
Podmínky jsou v DynSQL editoru definovány pomocí SQL fragmentů. V závislosti na vlastnostech těchto fragmentů se podmínky v těle požadavku (resp. hodnota "value") definují různými způsoby:
-
Některé podmínky hodnotu nemají (typicky mají fragmenty deklarované v subzáložkách Link nebo Special). V uvedeném příkladu jde o jednotku Rows, kde se pomocí flagu nastavil výběr včetně dokumentů bez řádků (WithDocumentsWithoutRows) a podmínka ESLCompleteKind (Jen nevyplněné pro ESL), která má spec. subtyp 11 (v těle Web API požadavku ji stačí jen použít, do SQL se doplní fragment v podobě definované v sekci Special v DynSQL editoru).
Datový typ a subtyp jsou součástí definice podmínky (v DynSQL editoru se zobrazují v horní části záložky Podmínky).
-
Některé podmínky podporují právě jednu hodnotu. (V příkladu například podmínka Description.)
Jednu hodnotu je možné použít i v případě podmínky reprezentující vazbu na číselník - pro podmínku “Firm_ID” by hodnota mohla vypadat i takto: “value”: “X000000101”.
- Některé podmínky podporují právě dvě hodnoty (rozsah). Typicky se jedná o podmínku typu datum, v příkladu podmínka DocDate.
- Některé podmínky podporují více než dvě hodnoty (seznam). Typicky se jedná o výběr množiny ID z číselníků, v příkladu podmínka Firm_ID.
-
Některé podmínky se editují ve speciálním režimu a vyžadují zadání speciální hodnoty - viz definice v DynSQL editoru:
-
Podmínka SimplifiedVATDocument (Zjednodušený daňový doklad) je typu boolean (v DynSQL editoru ctBoolean), povolené hodnoty true nebo false.
-
Podmínka TradeType (Typ obchodu) je spec. subtyp 14 - v definici má deklarován seznam názvů a hodnot oddělených středníkem. Jako hodnotu je třeba zadat podmnožinu seznamu hodnot oddělených středníkem. V aplikaci ABRA Gen je reprezentována sadou přepínačů.
-
Podmínka IntrastatCompleteKind (Jen nevyplněné pro INTRASTAT) je spec. subtyp 1 - v definici má deklarován seznam názvů a hodnot oddělených středníkem. Do podmínky je zapotřebí předat právě jednu hodnotu ze seznamu. V aplikaci ABRA Gen je reprezentována zatrhávací položkou.
-
Pro datumové podmínky platí následující:
Pokud některá z hodnot podmínky typu datum obsahuje také čas, pak podmínka omezuje i za čas. V aplikaci ABRA Gen tomu odpovídá přepínač "Zadávat i čas". Hodnotu je možné zadat textově ve formátu ISO 8601 (např. "2020-10-14T06:00:00") anebo číselně tak, jak je uložena v databázi.
Vrácený JSON obsahuje objekt s následujícími vlastnostmi:
Vlastnost | Význam | Komentář |
---|---|---|
"name" | Název datasetu. | |
"items" |
Pole vrácených objektů. Může obsahovat pole podřízených datasetů "datasets” v případě, že výsledek nějaké podřízené datasety obsahuje. |
Pole datasetů jsou do sebe vnořená podle definice DynSQL. Dataset VATRates (Sumář DPH) je podřízený datasetu MAIN. Dataset BATCHES (Pohyby sériových čísel a šarží) je podřízený datasetu ROWS (Řádky). Dataset ROWS není v níže uvedeném dotazu explicitně uveden, proto se připojil automaticky a nevrátil žádné položky (samotné řádky), jen data sobě podřízených datasetů (pohyby sériových čísel a šarží). Struktura datasetů v definici DynSQL vypadá následovně:
|
Požadavek:
POST http://localhost:699/demodata/dynsql/40SBPEINEFD13ACM03KIU0CLP4/exec
Tělo požadavku:
{
"select": ["ID", "DocQueue_Code", "Period_Code", "OrdNumber", "NotPaidAmount", "DocDate$DATE"],
"where" : {
"id": "ID",
"value": "2E00000101"
},
"datasets": [
{
"name": "batches",
"select": ["PosIndex", "qunit", "unitrate"]
},
{
"name": "vatrates",
"select": ["VRVATUsageRowsCount", "Name"]
}
]
}
Výsledek zpracování požadavku:
Status: 200 OK
{
"name": "MAIN",
"items": [
{
"ID": "2E00000101",
"DOCQUEUE_CODE": "FV",
"PERIOD_CODE": "2020",
"ORDNUMBER": 5,
"NOTPAIDAMOUNT": 0,
"DOCDATE$DATE": "2020-10-14T22:00:00.000Z",
"datasets": [
{
"name": "ROWS",
"items": [
{
"datasets": [
{
"name": "BATCHES",
"items": []
}
]
},
{
"datasets": [
{
"name": "BATCHES",
"items": []
}
]
},
{
"datasets": [
{
"name": "BATCHES",
"items": [
{
"POSINDEX": 1,
"QUNIT": "ks",
"UNITRATE": 1
}
]
}
]
},
{
"datasets": [
{
"name": "BATCHES",
"items": []
}
]
}
]
},
{
"name": "VATRates",
"items": [
{
"VRVATUSAGEROWSCOUNT": 0,
"NAME": "základní sazba"
}
]
}
]
}
]
}
Požadavek:
POST http://localhost:81/data/dynsql/40SBPEINEFD13ACM03KIU0CLP4/exec?report=W400000001
V HTTP hlavičce požadavku je v třeba položku Accept nastavit na hodnotu application/pdf.
Tělo požadavku:
{
"select": "ID",
"where": [
{
"id": "ID",
"value": [
"1400000101"
]
}
]
}
Výsledkem dotazu je vrácení PDF k tisku.
Status: 200 OK