Spousteni Dispatch
-----------------------------

- instaluje se do C:/atx300
- spousti se pomoci dispatch.exe --db ./data.db
- neni-li pri startu nalezen databazovy soubor:
    - dispatch jej automaticky vytvori a nainicializuje prazdnymi tabulkami.
    - je-li nalezen adresar se starymi daty ("/atx300/minidisp/data/cs/"), pak jsou tato data
      automaticky naimportovana a adresar je prejmenovan na prefix "_imported"
- dalsi parametry lze ziskat spusenim dispatch.exe -h

Import starych dat
-----------------------------

- neni-li pri startu nalezen databazovy soubor a je li zaroven nalezen adresar se starymi daty
  ("/atx300/minidisp/data/cs/"), pak jsou tato data automaticky naimportovana a adresar je prejmenovan na prefix "_imported"
- data z DBF souboru (atxd300) jsou importovana pomoci parametru --import-atxd300 nebo --import-atxd300-path=<path>
  Adresar s DBF soubory je importovan pouze jednou, pote je prejmenovan na <jmeno>_imported
  Importuji se pouze Vozidla, Stavby a Odberatele
  Poznamka: Obvykly DBF adresar je /asterix/atxd300/data

Druhy provozu
-----------------------------

Atxdispatch muze fungovat ve trech ruznych rezimech:

 - standard: V tomto rezimu je jedinym, a tedy i hlavnim, dispecerskym programem. Zapisuje soubory do dis_man, cte soubory
             z man_dis. Zapisuje soubor material.ini.
 - bridge:   V tomto rezimu je hlavnim dispecinkem jiny (externi) program. Atxdispatch tedy komunikuje na dve strany. Jedna
             strana je nas klasicky ridici system a komunikace z/do tohoto systemu probiha stejne jako ve standardnim rezimu.
             Na druhou stranu, k nadrazenemu dispecerskemu systemu, pak atxdispatch komunikuje pomoci dalsi dvojice adresaru.
             Konkretni pojemovani a format se muze lisit podle dane implementace. Na zaklade objednavek prijatych z nadrazeneho
             systemu si atxdispatch plni vlastni databazi. V tomto rezimu atxdispatch zapisuje soubor material.ini.
             Jednotlive mustky mohou mit sve specificke nastaveni a vyjimecne chovani.
 - standby:  Tento rezim se podoba rezimu bridge. Tentokrat ale atxdispatch nestoji "mezi" ridicim systemem a nadrazenym
             dispecinkem, ale je provozovan "vedle". Hlavni (externi) dispecink zapisuje soubory primo do dis_man a cte je
             z man_dis. Externi dispecink take zapisuje material.ini. Krome toho existuje jeste specialni adresar, ze ktereho
             atxdispatch cte veskere komunikacni soubory a interne si aktualizuje databazi. Na soubory v man_dis nesaha (nechava
             je tam pro externi dispecink). Stejne tak soubor material.ini je z pohledu atxdispatch pouze pro cteni. Komunikacni
             soubory do specialniho adresare prubezne kopiruje externi program (v nasem pripade manager pomoci funkce extra_copy_to).

Databáze
-----------------------------
Databaze je pri ukonceni zalohovana do souboru history/dispatch/<timstamp>.sqlite3
(pokud podadresare neexistuji, jsou automaticky vytvoreny)

Integritu dat lze ověřit spuštěním dispatch.py --integrity-check : vypíše do logu všechny logické problémy s existujícími daty.
Může změnit data v databázi.

Ostatni
-----------------------------

Pro zjistovani teploty se pouziva Asterix aplikace Thermometer. Ta musi byt spustena (dispatch toto nezajistuje)
a jeji vystupni soubor byt nakonfigurovan v souboru /atx300/conf/thermometer.ini
Debug tip: pri kazde objednavce Dispatch zapisuje do logu stav cteni teploty vcetne zjistenych chyb

Konfigurace featur vetsiho dispecinku
---------------------------------------

Dispatch pouziva konfiguracni soubor /atx300/conf/dispatch.hjson
Je urcen k zapinani rozsirujicich modulu v zavislosti na konkretni instalaci.
Neni-li nalezen, Dispatch se chova, jako by vsechny rozsirujici moduly byly vypnuty.

Obsahuje hodnoty typu module_<modulename>: true|false , zapinajici jednotlive moduly, a dalsi nastaveni
Default je vzdy false
    module_cars              databaze aut
    module_contracts         databaze zakazek. Je-li zadano, je pristupna rovnez databaze staveb a odberatelu.
    module_login             prihlasovani pomoci databaze uzivatelu. Viz Management uzivatelu nize.
    module_delivery_sheets   Tiskove sestavy dodaciho a zamesoveho listu
    module_statistics        Vsemozne statistiky
    module_stock             Naskladnovani materialu
    module_pumps             Cerpadla
    module_prices            Veci tykajici se cen:
                               - zobrazeni a uprava cen v expedicnim dialogu
                               - editace specialnich cen pro jednotlive zakazniky
                               - prodej materialu (vcetne ceniku materialu a danovych dokladu za prodej)
    module_samples           featura automaticke hlaseni / odber vzorku.
                             Frekvenci vzorku (v receptech) lze zadavat, i kdyz je featura vypnuta
    ares_disabled            Je-li nastaveno, nezobrazuje UI tlacitko "ARES"
    rpo_disabled             Je-li nastaveno, nezobrazuje UI tlacitko "RPO" (Register právnických osôb)
    continuous_mode_enabled  Je-li nastaveno, umožnuje expedovat v kontinuálním režimu
    standby_path             Je-li nastaveno, chova se jak je popsano vys, v sekci "Druhy provozu"
    transport_zones          Je-li nastaveno, betonarka pouziva cenik dopravy definovany zonove.
                             V takovem pripade nelze zadat u vozidel cenu za kilometr.
                             (plati jen pro prepravu betonu, cerpadla toto nastaveni neovlivni)
    currency_rounding_precision  Pocet desetinnych mist, na nez se zaokrouhluji ceny (v tiskovych sestavach i vypisech). Default 2
                                 (drive se jmenovalo "rounding_precision", stary nazev je stale podporovan pro zpetnou kompatibilitu)
    tonnes_rounding_precision  Pocet desetinnych mist pro zobrazeni tun na dodacim listu. Default 3
    volume_rounding_precision  Pocet desetinnych mist pro zobrazeni objemu (m³). Default 2
    distance_rounding_precision  Pocet desetinnych mist pro zobrazeni vzdalenosti (km). Default 0


Tiskove sestavy
------------------

Automaticky tisk dodacich listu se zapina/vypina v dialogu nastaveni.

Logo do dodacího listu:

Program automaticky doplní do hlavičky dodacího listu logo, které se pokusí najít pod jménem "static/delivery_sheet/logo/<logo_fn>", kde <logo_fn> je specifikovano v konfiguracnim souboru.

Management uzivatelu
------------------------------------
Spust program s parametrem --users.
Master heslo je "PeroxidBetonu"

Uživatele poté může ve standardním UI editovat kdokoliv s příslušnými právy.
Zamykání tabulek: uživateli lze zamknout pro zápis některé tabulky (číselníky); změna se na úrovni databáze
projeví okamžitě, nicméně pokud je uživatel přihlášen, musí udělat refresh (F5), aby §viděl§ zamčené tabulky
ve svém UI (tzn. zobrazení ikonek zámečku v menu, skrytí tlačitek na editaci a podobně)

Externi url (pro nastaveni vyjimek ve firewallu)
------------------------------------

Minidisp se pripojuje na:

https://ares.gov.cz/ekonomicke-subjekty-v-be/rest/ekonomicke-subjekty/<XXXXXXX>

Aplikace thermometer se pripojuje na:

http://wttr.in/<XXXXXXX>?format=j1
A nějakou adresu zadánu v congigu thermometru, via funkci read_temperature_from_thermometer_protocol_1
(informace ohledne thermometer nejsou zaruceny, doporuceno prekontrolovat v jejim manualu)

REST API (/api/v1)
----------------------------------------

Dispatch nabízí verzované REST API na cestě /api/v1. Je VYPNUTÉ by default;
zapíná se parametrem příkazové řádky --api.

API běží na stejném portu jako webové rozhraní (výchozí 7781) - nepřidává žádný
další naslouchací port ani odchozí spojení, pouze přidává routy na již existující port.

Self-dokumentace (po zapnutí --api):
  - http://localhost:7781/api/v1/docs          HTML stránka s popisem (bez JavaScriptu)
  - http://localhost:7781/api/v1/openapi.json  generovaný OpenAPI spec

Vlastnosti:
  - resource-orientované CRUD endpointy pro zapnuté moduly (vypnutý modul -> 404, vypnuté pole -> 422)
  - stránkování, filtrování a řazení; NULL nenajde žádný porovnávací operátor, filtruje se
    přes :isnull: (např. ?filter=batch_id:isnull:true, resp. :isnull:false pro IS NOT NULL)
  - GET /api/v1/capabilities a GET /api/v1/enums pro discovery
  - vytvoření-a-odeslání objednávky: POST /api/v1/orders, zrušení: POST /api/v1/orders/{id}/cancel
    - podmínky kontrolované při odeslání (každá při porušení = 422): povinné volume a existující
      recipe_id; vozidlo (vehicle_id) povinné, není-li continuous_mode; a je-li zapnut modul cen,
      musí být receptura nacenená (POST /pricelist-recipes - s pricelist_id pro konkrétní
      ceník, nebo bez něj pro výchozí ceník), jinak je objednávka odmítnuta s no_price_for_recipe
  - cizí klíče jsou na drátě jako holé id (<x> -> <x>_id); interní pole s podtržítkem
    (např. _search_string) nejsou přes API přístupná pro čtení ani zápis
  - při zápisu posílejte jen zapisovatelná pole: read-only pole (zejména id, které
    přiděluje server) a neznámá pole se odmítnou s 422, nikoli ignorují
  - některá pole mají podmíněná pravidla, která typ nevyjádří, ale OpenAPI je popisuje
    (rozsah Material.density v kg/l; pole Surcharge závislá na price_type) - porušení = 422

API funguje i za reverse-proxy na podadresáři (např. /dispatch/api/v1) - Location
hlavičky a stránkovací odkazy jsou relativní.

Testování produkce pomocí curl příkazu
----------------------------------------

Produkce je vázána na autentizaci. Pokud dispečink běží v "mini" režimu, tj. bez zapnutého
modulu module_login, lze produkovat i bez přihlášení (bezpečnostní díra by design, btw).

Se zapnutým module_login je třeba nejprve se přihlásit, to je ovšem vnitřně manageováno přes session
(dispečing nepodporuje HTTP SIMPLE AUTH), a správu session curl (afaik) neumí.

TLDR: curlem lze posílat objednávky pouze je-li vypnut module_login, vše další vyžaduje přestavbu (po konzultaci, neboť bezpečnost).

Recept je identifikován pomocí recipe_id, které odpovídá našemu vnitřnímu ID v databázi.
Nejde tedy o "number" zobrazené v uživatelském rozhraní.
Pro jednoduché testy lze používat nízká ID receptů, která pravděpodobně existují,
při neexistujícím ID dispečink zahlásí srozumitelnou chybu.

Dispečink samozřejmě musí běžet, buď v zkompilované verzi, nebo jej spustit spustit v jednom okně termínálu
a z druhého posílat curl příkazy.

Jednoduchá produkce:

curl http://localhost:7781/produce --request POST --header "Content-Type: application/json" --data '{"recipe_id": 1, "volume": 1, "vehicle_id": "AAB 1111"}'

Složitější produkce:

curl http://localhost:7781/produce --request POST --header "Content-Type: application/json" --data '{"recipe_id": 1, "volume": 10, "vehicle_id": "AAB 1111", "without_water": true, "comment": "Přidáno pomocí curl", "temperature_air": 22.1, "customer_name": "Bořek stavitel", "construction_site_name": "Opera v Sydney"}'
