GIS oddělení v našem městě potřebovalo způsob, jak mohou obyvatelé hlásit výmoly, úniky vody, graffiti, nelegální skládky, problémy s předpisy a podobné záležitosti, a aby zaměstnanci mohli tyto požadavky řešit bez třetí strany 311 produktu. Postavili jsme to na ArcGIS Enterprise, který už provozujeme, a nyní jsme celý systém zveřejnili na GitHubu, zjednodušený tak, aby si ho mohla nasadit jakákoli organizace.
https://community.esri.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fgithub.com%2Fbrianmcleer%2Freport-a-concern
Tento příspěvek je technickým průvodcem, jak je systém sestaven a proč byla některá rozhodnutí učiněna. Repozitář obsahuje kompletní návod k nasazení.
Co je v balíčku
Dva widgety Experience Builder 1.21 (průvodce veřejným podáním a správce tiketů pro zaměstnance), schéma enterprise geodatabáze s atributovými pravidly, malý Flask proxy server před veřejnou feature službou, sedm Python skriptů běžících ve Windows Task Scheduleru, přístupné HTML šablony e-mailů, definice úloh Task Scheduleru a dokumentace. Nic v kódu není vázáno na naši organizaci. Hostnames, e-mailové adresy, názvy oddělení a ID položek pocházejí ze dvou git ignorovaných konfiguračních souborů a nastavení widgetů.
Datový model
Vše je uloženo v jedné enterprise geodatabázi SQL Serveru. Systém záznamů je bodová feature třída Tickets s GUID ID tiketu, čitelným číslem tiketu, kategorií jako podtypem (13 kódů), textovým polem podkategorie s hodnotami domény měnícími se podle podtypu, stavem, přiřazeným oddělením, hranicí oblasti, do které bod spadá, kontaktními údaji o podavateli a dvěma příznaky sledovanými skripty: notification_sent a survey_sent. K tiketům jsou povoleny přílohy pro fotografie.
Kolem toho jsou související tabulky propojené přes ID tiketu pomocí kompozitních relačních tříd tak, že smazání tiketu kaskádovitě smaže i související záznamy: Ticket_Comments (s příznakem is_public a email_sent), Ticket_Photos_Meta a Survey_Responses. Tři lookup tabulky řídí směrování: Service_Boundaries (polygony s příznakem is_active), Category_Boundary_Lookup (které kategorie jsou platné v jaké oblasti plus přesměrovací zpráva pro neplatné) a Ticket_Routing (kategorie, volitelná podkategorie, ID hranice, výchozí oddělení, e-mail oddělení). Notification_Log je auditní tabulka pouze pro přidávání záznamů, do které zapisují všechny skripty i proxy.
Tikety, komentáře a odpovědi na průzkumy jsou verzovány a archivovány. Lookup tabulky a Notification_Log nejsou verzovány záměrně, což má význam níže.
Průběh podání od začátku do konce
- Obyvatel otevře veřejnou aplikaci Experience Builder a umístí pin. Widget pro podání dotazuje Service_Boundaries na klientské straně, aby zjistil aktivní polygony obsahující bod, pak dotazuje Category_Boundary_Lookup tak, aby seznam kategorií zobrazoval jen platné možnosti. Tiket na vodu nelze podat v sousedním vodárenském obvodu; obyvatel místo toho vidí kontaktní informace tohoto obvodu místo slepé uličky.
- Widget odesílá applyEdits na URL stejného původu pod aplikací, nikoli přímo na feature službu. IIS URL Rewrite (na úrovni webu, takže republika Experience Builder to nesmaže) přeposílá tuto cestu na Flask proxy běžící na localhost přes Application Request Routing. Druhé pravidlo na úrovni webu vrací 403 na jakýkoli přímý POST na FeatureServer zvenčí.
- Proxy omezuje rychlost podle IP klienta, odmítá více než jeden prvek na požadavek, kontroluje geometrii vůči ohraničujícímu boxu, validuje kategorii, délku popisu, formát e-mailu a telefonu a teprve potom přeposílá požadavek na FeatureServer na localhostu. U fotografií čte první bajty a přijímá pouze skutečný JPEG, PNG, WebP a HEIC bez ohledu na deklarovaný typ s omezením velikosti. Každý přijatý i odmítnutý požadavek se zapisuje do Notification_Log s IP klienta pro audit bez ukládání do souboru.
- Pět Arcade atributových pravidel běží při vložení do geodatabáze: omezení geofence (blokuje mimo rozsah nebo neplatné kategorie s hláškou z lookup tabulky), výpočet směrování hledající hranici a pokus o shodu kategorie + podkategorie + hranice v Ticket_Routing s fallbackem na obecný řádek kategorie pro nastavení přiřazeného oddělení; výpočet čísla tiketu čerpající ze SQL sekvence začínající na 10000; dvě validační omezení pro povinná pole a obchodní pravidla. Směrování je data, ne kód: přidání oddělení nebo změna odpovědnosti za vodní tikety v jednom obvodu je editace řádku.
- Každých pět minut skript notifikace nových tiketů najde tikety s notification_sent = 0, pošle obyvateli potvrzovací e-mail se statusem odkazu a e-mailem upozorní přiřazené oddělení s odkazem do manažerské aplikace.
Pro zaměstnance
Manažerský widget běží v interní aplikaci Experience Builder za přihlášením Portal. Čte vrstvu Tickets a související tabulky z webové mapy bez potřeby dalších tokenů nebo URL služeb. Zaměstnanci filtrují podle stavu, kategorií a odznaků oddělení; otevírají tiket; mění stav (změna stavu vyžaduje komentář; zpětné datování vyřešeného data zapíše interní auditní poznámku); přidávají veřejné nebo interní komentáře; zobrazují fotografie v lightboxu; vidí odpověď průzkumu pokud dorazila. Veřejné komentáře spouštějí e-mail obyvateli přes skript maileru komentářů. Je zde export do Excelu se souhrnným listem a souvisejícími záznamy. Nápověda je zabudována ve widgetu podle vzoru používaného u všech našich widgetů.
Skripty a dvě chyby z prvního nasazení
Sedm skriptů sdílí jeden společný modul pro konfiguraci, logování, upozornění o chybách, e-maily, vykreslování šablon a zápisy auditu; každý skript tak obsahuje jen vlastní logiku: notifikátor nových tiketů; notifikátor přeřazení (detekuje změnu assigned_to a posílá e-mail novému oddělení); mailer veřejných komentářů; mailer pozvánek do průzkumu (spouští se při stavu Resolved nebo Closed); tahání odpovědí Survey123 (zapisuje do Survey_Responses a e-mailem informuje řešitele pokud obyvatel požádal o zpětné volání); týdenní report vedoucích o prošlých tiketech podle kategorií; měsíční report všech oddělení. Každá chyba během běhu se sbírá a posílá jako jedno upozornění při ukončení procesu; proces končí s kódem 1 aby to Task Scheduler zaznamenal.
Dvě lekce jsou zakódované v systému. První: duplicitní e-maily. Původní notifikátor posílal e-maily uvnitř jedné dávkové editace a commitoval příznak až nakonec. Pokud commit selhal (například když měl zaměstnanec tiket otevřený v manažeru – konflikt verzí), všechny e-maily už byly odeslány ale příznaky rollbacknuty – další běh tedy poslal všechny znova. Nyní se příznak commitne zvlášť pro každý tiket krátkou editací před odesláním e-mailu. Pokud commit selže – žádný e-mail není odeslán; bezpečné opakování při dalším běhu. Pokud commit uspěje ale odeslání selže – chyba se zaloguje a je viditelná ale nikdy se e-mail neodešle znovu.
Druhá lekce: auditní tabulka. Notification_Log byl původně verzovaný; zápisy přes kurzory byly pomalé a závislé na Compress operaci. Nyní není verzovaný; každý zápis provádíme přímým SQL insert s explicitním OBJECTID nastaveným jako MAX+1 s krátkým retry mechanismem – žádný zápis nezávisí na čítači řádků geodatabáze ani nedochází ke kolizím mezi skripty. S tím souvisí i problém maileru průzkumu: ten jednou četl základní tabulku bez verzování a neviděl vyřešení dokud nebyl spuštěn další Compress – průzkumy tak chodily opožděně o celý cyklus. Nyní každý skript čte přes verzovanou feature třídu.
Průběh průzkumu
Když je tiket vyřešený, obyvatel dostane odkaz na formulář Survey123 s ID tiketu v URL. Skript tahání načte nové odpovědi z ArcGIS Online, zapíše je do Survey_Responses v geodatabázi a pokud obyvatel požádal o zpětné volání, pošle e-mail zaměstnanci který tiket vyřešil (vyčteno z editor tracking s fallbackem na oddělení). Manažerský widget ukazuje hodnocení a komentáře u tiketu.
Bezpečnost a soukromí
Anonymní uživatelé mají právo číst veřejný pohled a mohou vytvářet pouze přes proxy. IIS hlavičky na úrovni webu nastavují HSTS, nosniff a frame options. Feature služba omezuje typy nahrávaných souborů i jejich velikost. Proxy nikdy nevěří deklarovanému typu obsahu. Uchovávání dat řeší sumarizační tabulky počítající podle měsíců, kategorií a oddělení bez ID tiketů či volného textu – staré tikety s osobními údaji lze tedy plánovaně mazat zatímco statistiky zůstávají zachovány.
Nasazení systému
Návod v docs/deployment.md je krok za krokem: vytvořit schéma pomocí arcpy skriptu (nejdřív suchý běh), publikovat tři služby (veřejný zápis, veřejné čtení, zaměstnaneckou), přidat atributová pravidla; vložit dva widgety do your-extensions a sestavit aplikace; nastavit IIS pravidla na úrovni webu; spustit proxy ve klonovaném ArcGIS Pro Python prostředí; vyplnit config.py a rac_secrets.py; importovat úlohy Task Scheduleru. Každý skript má zapnutý testovací režim takže nic neodešle skutečnému obyvateli dokud to nepřepnete. Dokument řešení problémů obsahuje tabulku symptom → příčina → oprava vytvořenou během migrace systému mezi servery: IIS HTML 500 znamená že proxy neposlouchá; 404 znamená že ARR není nainstalováno; CORS chyba znamená že URL widgetu není stejného původu jako stránka; chyba Windows Server 2025 Task Scheduler znamená že úloha ukazuje na základní ArcGIS Pro Python místo klonu.
Widget zipy jsou přiložené ke každému vydání na GitHubu. Problémy i pull requesty jsou vítány v repozitáři.