Práce s Úkoly prostřednictvím REST API ABRA Gen
Od verze 19.2 je k aplikaci ABRA Gen jako volitelný doplněk dodávána webová aplikace Úkoly sloužící ke správě úkolů.
S objekty spravovanými webovou aplikací Úkoly (tj. s úkoly, vazbami, přílohami, komentáři) je možné pracovat také prostřednictvím rozhraní Web API. Tímto způsobem lze rozšířit standardní funkcionalitu podle individuálních potřeb, např. zobrazovat úkoly ve firemním intranetu, automaticky generovat nové úkoly na základě vzniku určitých událostí apod.
Tato kapitola obsahuje popis vybraných Web API zdrojů pro příslušné objekty, jednoduché příklady použití a různé doplňující poznámky a tipy.
Úplný výčet možností naleznete v OpenAPI dokumentaci. Pro každý zdroj je zpravidla k dispozici kompletní sada metod (GET, POST, PUT a DELETE) umožňující čtení, vytváření, úpravy i mazání jednotlivých objektů.
Potřebujeme získat kolekci obsahující ID a názvy všech existujících úkolů.
GET http://localhost:699/data/tasks?select=id,summary
Výsledek zpracování požadavku:Status: 200 OK
[
{
"id": "1000000101",
"summary": "Úkol 1"
},
{
"id": "2000000101",
"summary": "Úkol 2"
}
]
Jedním z atributů úkolu je vazba na seznam úkolů (tasklist_id). Seznamy úkolů jsou chráněné objekty. Pokud seznamy úkolů používáte, v získané kolekci nebudou obsaženy úkoly zařazené do seznamů, ke kterým uživatel Web API nemá oprávnění.
Potřebujeme získat vlastnosti konkrétního úkolu (ID = 30B0000101).
GET http://localhost:699/data/tasks/30B0000101
Výsledek zpracování požadavku:
Status: 200 OK
{
"assignedto_id": "2300000101",
"classid": "Q1ZMZREFXWC45CR2NGZYW3R5OO",
"createdat$date": "2019-08-13T09:48:25.943Z",
"deadline$date": null,
"description": "Popis úkolu",
"displayname": "Název úkolu",
"id": "30B0000101",
"objversion": 4,
"owner_id": "1200000101",
"pmstate_id": "4000000001",
"ranking": 3652040,
"startat$date": null,
"summary": "Název úkolu",
"tasklist_id": null
}
Popis vybraných vlastností:
assignedto_id - ID řešitele (vazba do číselníku uživatelů), classid - PackedGUID třídy Úkoly (konstanta), createdat$date - datum vytvoření, deadline$date - termín, description - popis úkolu, owner_id = ID zadavatele, pmstate_id = ID stavu (vazba do číselníku procesních stavů), ranking = pořadí pro řazení v dashboardu, summary = název úkolu, tasklist_id = ID seznamu úkolů (vazba do číselníku seznamů úkolů)
Potřebujeme vytvořit nový úkol s požadovanými vlastnostmi.
POST http://localhost:699/data/tasks?select=id
Tělo požadavku:
{
"assignedto_id": "2300000101",
"description": "Popis úkolu",
"owner_id": "1200000101",
"pmstate_id": "4000000001",
"ranking": 3652040,
"summary": "Název úkolu"
}
Výsledek zpracování požadavku:
Status: 201 Created
{
"id": "50C0000101"
}
Význam jednotlivých vlastností viz předchozí oddíl Získání informací o existujících úkolech. Povinné jsou pouze hodnoty Stav a Zadavatel, ostatní vlastnosti se v případě vynechání nastaví na výchozí (prázdné) hodnoty.
Vlastnost ranking využívá webová aplikace Úkoly k řazení úkolů v dashboardu. Pokud má úkol nastavený termín, do pole ranking se ukládá číselná reprezentace termínu (počet dní od 1.1.1900). Pokud termín vyplněný není, dosadí se hodnota 2147483647 (aby byly úkoly bez termínu v dashboardu řazeny jako poslední). Při vytváření úkolů prostřednictvím Web API doporučujeme používat stejnou metodiku.
Potřebujeme změnit řešitele (ID úkolu 30B0000101, ID nového řešitele 1200000101).
PUT http://localhost:699/data/tasks/30B0000101?select=id,assignedto_id
Tělo požadavku:
{
"assignedto_id": "1200000101"
}
Výsledek zpracování požadavku:
Status: 200 OK
{
"id": "30B0000101",
"assignedto_id": "1200000101"
}
Pokud se pokusíte zařadit úkol do seznamu úkolů, ke kterému uživatel Web API nemá oprávnění, skončí požadavek chybou:
PUT http://localhost:699/data/tasks/30B0000101?select=id,tasklist_id
Tělo požadavku:
{
"tasklist_id": "1010000101"
}
Výsledek zpracování požadavku:
Status: 404 Not Found
{
"title": "Žádné záznamy",
"description": "Nebyly nalezeny žádné záznamy odpovídající zadaným kritériím"
}
Potřebujeme smazat úkol s ID = 30B0000101.
DELETE http://localhost:699/data/tasks/30B0000101
Výsledek zpracování požadavku:
Status: 204 No Content
Webová aplikace Úkoly aplikuje při mazání úkolů dodatečnou logiku - pokud uživatel smaže úkol (v grafickém rozhraní aplikace v prostředí internetového prohlížeče), k jeho odstranění dojde pouze v případě, že se úkol nacházel ve stavu Smazáno (resp. stavu navázaném na systémový stav Storno). V opačném případě se pouze změní stav úkolu na Smazáno. Jinými slovy, mazání úkolů v prostředí webové aplikace Úkoly je dvoufázové - první použití funkce Smazat způsobí změnu stavu úkolu, druhé použití téže funkce způsobí jeho smazání.
Toto chování je specifické pro webovou aplikaci Úkoly, samotné rozhraní Web API podobnou funkcionalitu neobsahuje. Pokud byste ji chtěli napodobit, bylo by zapotřebí provést několik kroků:
- po přijetí požadavku na smazání určitého úkolu zjistit jeho aktuální stav (pmstate_id)
- pokud stav odpovídá systémovému stavu Storno, pak úkol smazat (metodou DELETE)
- v opačném případě pouze změnit stav na některý ze stavů odpovídajících systémovému stavu Storno (metodou PUT)
Uživatelských procesních stavů odpovídajících systémovému stavu Storno může být nadefinovaných více. Webová aplikace Úkoly automaticky vybírá stav s nejnižší hodnotou Pořadí. Pokud chcete i toto chování napodobit, ID požadovaného stavu získáte následovně:
GET http://localhost:699/data/pmstates?select=id&where=systemstate+eq+4+and+clsid+eq+'Q1ZMZREFXWC45CR2NGZYW3R5OO'&orderby=sequencenumber&take=1
(Q1ZMZREFXWC45CR2NGZYW3R5OO je PackedGUID třídy Úkoly.)
Mějme fakturu vydanou, ID = 1N00000101. Potřebujeme získat kolekci obsahující ID a názvy úkolů připojených k této faktuře. Znovu připomínáme, že vrácená kolekce nebude obsahovat úkoly zařazené do seznamů úkolů, ke kterým uživatel Web API nemá oprávnění.
GET http://localhost:699/data/taskrelations?select=task_id.id,task_id.summary&where=clsid+eq+'O3BDOKTWEFD13ACM03KIU0CLP4'+and+obj_id+eq+'1N00000101'
(O3BDOKTWEFD13ACM03KIU0CLP4 je PackedGUID třídy Faktury vydané.)
Výsledek zpracování požadavku:
Status: 200 OK
[
{
"task_id.id": "1000000101",
"task_id.summary": "Úkol 1"
},
{
"task_id.id": "2000000101",
"task_id.summary": "Úkol 2"
}
]
Mějme fakturu vydanou s ID = 1N00000101. K této faktuře potřebujeme vytvořit úkol a fakturu s úkolem propojit vazbou.
Nejprve vytvoříme nový úkol, zatím na faktuře nezávislý, viz Vytvoření nového úkolu. V klauzuli select nezapomeneme uvést pole id - přidělené ID budeme potřebovat v dalším kroku. Předpokládejme, že nově vytvořenému úkolu bylo přiděleno ID = 50C0000101.
Následně vytvoříme vazbu mezi business objektem třídy faktury vydané a úkolem.
POST http://localhost:699/data/taskrelations
(O3BDOKTWEFD13ACM03KIU0CLP4 je PackedGUID třídy Faktury vydané.)
Tělo požadavku:
{
"clsid": "O3BDOKTWEFD13ACM03KIU0CLP4",
"obj_id": "1N00000101",
"task_id": "50C0000101"
}
Výsledek zpracování požadavku:
Status: 201 Created
{
"classid": "0JWD5HQPL1IONCKMDVR3A4OZ2W",
"clsid": "O3BDOKTWEFD13ACM03KIU0CLP4",
"displayname": "1080000101",
"id": "1080000101",
"obj_id": "1N00000101",
"objdisplayname": "FV-3/2018",
"objversion": 1,
"task_id": "50C0000101"
}
(0JWD5HQPL1IONCKMDVR3A4OZ2W je PackedGUID třídy Vazby úkolu na business objekt (TaskRelation).)
Vazbu vytvořenou v předchozím příkladu můžeme jednoduše odstranit s využitím metody DELETE:
DELETE http://localhost:699/data/taskrelations/1080000101
Výsledek zpracování požadavku:
Status: 204 No Content
Přílohou se v souvislosti s Úkoly rozumí jednak samotná data (obsah a případně náhled), jednak business objekt reprezentující přílohu, který se na data odkazuje, resp. definuje vazbu mezi úkolem a těmito daty. Při práci s přílohami prostřednictvím Web API je s touto skutečností nutné počítat.
Mějme vytvořený úkol s ID = 60B0000101. K tomuto úkolu chceme přiložit obrázek ve formátu PNG.
-
Nejprve naimportujeme obsah přílohy.
POST http://localhost:699/data/taskattachments/content?select=id
V hlavičce požadavku specifikujeme typ - Content-Type: image/png. (V případě neuvedení typu se použije výchozí hodnota application/octet-stream.)
Do těla požadavku vložíme samotný obrázek (binární data).
Výsledek zpracování požadavku:
Status: 201 Created
{ "id": "1070000101" }
-
Obdobným způsobem vložíme náhled přílohy. Tento krok je volitelný. Pokud k příloze existuje náhled, zobrazuje se ve webové aplikaci Úkoly na záložce Přílohy, v opačném případě se zobrazuje prázdná dlaždice s uvedením typu.
POST http://localhost:699/data/taskattachments/preview?select=id
V hlavičce požadavku opět specifikujeme typ Content-Type: image/png a do těla požadavku vložíme samotný náhled obrázku (binární data).
Pokud je náhledem obrázek, z estetických důvodů je vhodné používat čtvercové náhledy o velikosti 200 × 200 pixelů (náhledy se při zobrazení ve webové aplikaci Úkoly roztahují na celou plochu dlaždice).
Výsledek zpracování požadavku:
Status: 201 Created
{ "id": "2070000101" }
-
V posledním kroku vytvoříme business objekt přílohy.
POST http://localhost:699/data/taskattachments?select=id
V těle tohoto požadavku specifikujeme název přílohy (souboru), vazbu na úkol, na obsah a volitelně také na náhled.
{ "name": "picture.png", "task_id": "60B0000101", "content_id": "1070000101", "preview_id": "2070000101" }
Výsledek zpracování požadavku:
Status: 201 Created
{ "id": "2040000101" }
Pokud při vytváření příloh využijete transakční zpracování a všechny kroky spojíte do jedné dávky (uložení dat obsahu, dat náhledu a vytvoření objektu přílohy), předejdete potenciálnímu problému se vznikem osiřelých příloh.
Přílohu vytvořenou v předchozím kroku chceme odstranit, včetně vazby na úkol.
Stejně jako vytváření přílohy, i její odstraňování se bude skládat z několika kroků. Budeme postupovat v opačném pořadí - mezi přílohou a jejími daty existuje referenční integrita a odstranit data, na která se odkazuje business objekt přílohy, by se nepodařilo.
-
Nejprve tedy odstraníme business objekt samotné přílohy.
DELETE http://localhost:699/data/taskattachments/2040000101
Výsledek zpracování požadavku:
Status: 204 No Content
-
Následně odstraníme data obsahu (na pořadí odstraňování dat obsahu a náhledu již nezáleží).
DELETE http://localhost:699/data/taskattachmentdata/1070000101
Výsledek zpracování požadavku:
Status: 204 No Content
-
Stejným způsobem odstraníme data náhledu.
DELETE http://localhost:699/data/taskattachmentdata/2070000101
Výsledek zpracování požadavku:
Status: 204 No Content
V praxi může nastat situace, kdy se z nějakého důvodu uloží data přílohy (obsah nebo náhled), ale již se nevytvoří objekt přílohy, který se na tato data odkazuje. Data příloh pak zůstanou uložena v databázi, ale nevyužívají se a nejsou uživatelsky dostupná. Pomocí níže uvedeného Web API požadavku (příklad použití rozšířeného dotazování) můžete získat seznam uložených dat příloh (obsahů a náhledů) a následně odstranit ta z nich, která nejsou přiřazená k žádným přílohám.
POST http://localhost:699/data/taskattachmentdata/query
Tělo požadavku:
{
"select": [
"id",
{
"name": "attachments",
"value": {
"class": "taskattachments",
"select": ["id"],
"where": "content_id = :id or preview_id = :id"
}
}
]
}
Výsledek zpracování požadavku:
Status: 200 OK
[
{
"id": "1000000101",
"attachments": []
},
{
"id": "2000000101",
"attachments": []
},
{
"id": "1020000101",
"attachments": [
{
"id": "1000000101"
}
]
},
{
"id": "1030000101",
"attachments": []
},
{
"id": "2040000101",
"attachments": [
{
"id": "2010000101"
}
]
}
]
Obsahy příloh (attachmentdata) s ID 1000000101, 2000000101 a 1030000101 můžete smazat, protože nejsou navázané na žádnou přílohu. Ke smazání použijete metodu DELETE a zdroj /taskattachmentdata, viz kroky 2 a 3 ve výše uvedeném příkladu.
Potřebujeme vypsat komentáře k úkolu s ID = 1000000101.
GET http://localhost:699/data/taskcomments?select=id,createdat$date,createdby_id.name,text&where=task_id+eq+'1000000101'
Výsledek zpracování požadavku:
Status: 200 OK
[
{
"id": "1000000101",
"createdat$date": "2019-08-13T07:23:43.583Z",
"createdby_id.name": "Jaroslav Novák",
"text": "Komentář #1"
},
{
"id": "2000000101",
"createdat$date": "2019-08-13T07:24:32.330Z",
"createdby_id.name": "Václav Kuchta",
"text": "Komentář #2"
}
]
Potřebujeme přidat komentář k úkolu s ID = 1000000101.
POST http://localhost:699/data/taskcomments
Tělo požadavku:
{
"task_id": "1000000101",
"text": "Komentář 3"
}
Výsledek zpracování požadavku:
Status: 200 OK
{
"classid": "3ANM11UGRKC4FGBJXHY3DKB5FC",
"createdat$date": "2020-01-07T12:56:31.397Z",
"createdby_id": "1C00000101",
"displayname": "2030000101",
"id": "2030000101",
"objversion": 1,
"task_id": "1000000101",
"text": "Komentář 3"
}
Komentář přidaný v předchozím příkladu opět odstraníme.
DELETE http://localhost:699/data/taskcomments/2030000101
Výsledek zpracování požadavku:
Status: 204 No Content
Ve webové aplikaci Úkoly není odstraňování komentářů podporováno. Prostřednictvím Web API můžete komentář odstranit, ale tato akce nevygeneruje žádnou notifikaci.
Kromě ilustračních příkladů uvedených v jednotlivých sekcích se při tvorbě vlastních řešení můžete inspirovat také samotnou webovou aplikací Úkoly. V internetovém prohlížeči (Chrome, Firefox...) si aktivujte Nástroje pro vývojáře a následně můžete v aplikaci provádět různé operace a ve vývojářském okně (na záložce Síť) souběžně sledovat požadavky, které aplikace na pozadí odesílá. Aplikace často využívá dávkové/transakční zpracování, takže například při vytváření nového úkolu můžete odchytit následující požadavek:
POST http://localhost:699/data/batch?app=tasks
Tělo požadavku:
{"items":[{"id":"task","type":"create","allow_expr":false,"data":{"class_id":"tasks","object_data":{"assignedto_id":"2D00000101","deadline$date":"2020-01-08","description":"Popis úkolu","owner_id":"1200000101","pmstate_id":"4000000001","ranking":737432,"summary":"Název úkolu","tasklist_id":"1010000101"},"query":{"select":["id"]}}}]}