Co je to?
Poznámka pro administrátory: Sady pravidel rozhodují, co aplikace udělá sama: které faktury dostanou upomínku, kdo schvaluje přijatý doklad, jak se k řádku přijaté faktury najde produkt, kolik se objedná u dodavatele, co automatizace udělá, když je objednávka zaplacená. Většině firem stačí zapnout hotová pravidla a vyplnit jejich nastavení (Nastavení > oblast pravidel). Psaní vlastních pravidel v tomto jazyce je práce pro konzultanta nebo vývojáře – nebo pravidlo popište větou a nechte ho napsat AI asistenta v dialogu pravidel.
Hlavní body:
- Jeden jazyk všude: upomínky, schvalování, příjem dokladů, nákup, párování plateb, placení, expedice, doprava, sklad i automatizace používají stejné sady pravidel.
- Bezpečné: pravidlo čte jen fakta, která jeho oblast nabízí, a dělá jen akce, které oblast dovoluje; každý výsledek říká, které pravidlo ho způsobilo („Proč“).
- Vyzkoušet před uložením: tester sad pravidel sadu zkontroluje a spustí ji na faktech, která zadáte.
Sady pravidel
Sada pravidel je text pravidel ve formátu Markdown pro pravidlový engine. Každá sada patří do jedné oblasti (domény):
upomínky, schvalování dokladů, příjem dokladů, nákup, párování plateb, placení, expedice, doprava, skladové oblasti a
automatizace. Oblast určuje, co pravidla smí číst (fakta), rozhodnout (cíle), dohledat (hledání) a udělat
(akce) a kdy se spouštějí. Tato stránka popisuje jazyk; co nabízí která oblast (fakta, cíle, hledání, akce a
spouštěče), ukáže tester sad pravidel pro vybranou oblast a MCP server jako
doc://rulebook-domains. Pravidlo smí použít jen to, co jeho oblast deklaruje.
1. Sada pravidel
# Upomínky
domain: dunning
const minimum = 50
const firstTemplate = 'UPOMINKA-1'
## Neupomínat malé částky
> Faktura, na které zbývá zaplatit méně než nastavená částka, se neupomíná.
id: minimum
when: remaining < minimum
stop
## 1. upomínka
> Několik dní po splatnosti dostane partner první upomínku se všemi fakturami po splatnosti.
id: first
level: 1
when: daysOverdue >= 3 and reminderLevel < 1
do sendMessage firstTemplate group by partner.id once
- První řádek
# <název>je název sady. Nadpis#smí být jen jeden. - Řádky hlavičky jsou před prvním pravidlem:
domain: <oblast>(povinný);const <název> = <hodnota>(nastavení, která pravidla používají jménem);scope: <entity>neboscope: *,language: <kód>,disable: <id pravidel>,secret: true|false.
## <název pravidla>začíná pravidlo (uzel).### <pravidlo>pod ním je konkrétnější pravidlo: platí jen tehdy, když platí i podmínka nadřazeného. Úroveň nadpisu se nesmí přeskočit.- Řádky pod pravidlem, zvykem v tomto pořadí:
| Řádek | Význam |
|---|---|
> <text> |
popis pravidla (jedna věta, v jazyce uživatelů) |
id: <id> |
stálé id: písmena, číslice, -, _; v sadě jedinečné. Bez něj se id vytvoří z názvu |
on: <spouštěče> |
kdy se pravidlo spouští (jen oblasti se spouštěči, oddíl 6) |
when: <podmínka> |
podmínka pravidla (oddíl 3); pravidlo bez when: platí pro každý předmět |
default: on|off |
hotové pravidlo zapnuté nebo vypnuté, dokud firma nerozhodne |
level: <n> |
úroveň pravidla (stupeň upomínky, úroveň schvalování) |
automation: off|suggestOnly|assisted|full |
jak samostatně pravidlo jedná; nahrazuje úroveň oblasti |
excludes: <id> |
hotová pravidla, která nemohou být aktivní zároveň s tímto |
validFrom: <rok>, validTo: <rok> |
roky, kdy pravidlo platí |
secret: true |
text pravidla se nikdy neposílá do prohlížeče |
param <název>: <typ> [= <výchozí>] ["<popisek>"] |
parametr hotového pravidla (oddíl 7) |
| příkazy | co pravidlo dělá (oddíl 2) |
//začíná komentář. Jiný řádek, který není direktiva ani příkaz, je volný text a ignoruje se.
2. Příkazy
Oblast dovoluje jen některé příkazy: kontrola nahlásí příkaz, který oblast neuvádí.
| Příkaz | Význam |
|---|---|
set <cíl> = <hodnota> [when <podmínka>] |
rozhodne hodnotu cíle |
suggest <cíl> = <hodnota> [confidence <0–1>] [when <podmínka>] |
doporučí hodnotu; nikdy nerozhoduje |
restrict <cíl> in (<hodnoty>) |
povolené hodnoty cíle |
check <podmínka> else block|error|warning|info "<zpráva>" |
nález, když podmínka neplatí; block zastaví výsledek (nepřipraveno, neobjednáno, neodesláno) |
try <cíl> by <hledání> [<argumenty>] [as suggest] [when <podmínka>] [then set|suggest …] |
dohledání; pokusy běží v zapsaném pořadí a vyhrává první, který najde právě jeden |
else ask ["<otázka>"], else skip, else create <entita> with <pole> = <hodnota>, … |
co se stane, když žádný try nenašel právě jeden |
do <akce> <argumenty> [when <podmínka>] [once | once per <n> days | every <n> days | always] [group by <hodnota>] |
akce; výchozí je once |
let <název> = <hodnota> |
fakt pravidla, který mohou použít příkazy za ním (oddíl 5) |
priority + <hodnota> | - <hodnota> | = <hodnota> [when <podmínka>] |
přičte k (nebo nastaví) skóre předmětu |
group <název> by <hodnota> [max <n>] [when <podmínka>] |
vytvoří skupiny předmětů; max může jmenovat nastavení |
cluster by <hodnota> [max <n>] |
seskupí podobné předměty |
stop |
pravidla za tímto se pro předmět už nepoužijí |
Jak vzniká výsledek
- Použije se každé pravidlo, jehož podmínka platí, v zapsaném pořadí.
stopukončí zbytek pro daný předmět. - Spustí se všechny akce
do, jejichž podmínka platí (ne jen první). Každá akce má klíč z sady, pravidla, akce a předmětu nebo skupiny, takžeonceopravdu proběhne jednou. - Více
setjednoho cíle: vyhraje nejkonkrétnější pravidlo (nejhlubší nadpis); stejně konkrétní jsou konflikt. - Vrstvy: systémové sady (hotová pravidla), pak metodika firmy, pak vlastní sady firmy v jejich pořadí.
checksblockpředmět zablokuje. Hlásí se všechny důvody blokace, ne jen první.
Kolekce: po řádcích, po složkách
Příkaz s předponou kolekce se spustí pro každý její prvek:
lines: try product by ean
lines: try product by supplierCode
lines: else ask "Vyberte nebo založte produkt pro ${name}"
lines: check priceDifference <= priceTolerance else warning "Cena ${name} se liší od poslední nákupní ceny"
lines: when: quantity > 0
Uvnitř kolekce se fakta prvku čtou jménem. Předmět se čte jménem nadřazeného, které oblast deklaruje, například
document.partner. <kolekce>: when: <podmínka> omezí prvky, na které pravidlo platí.
3. Podmínky
when:, when příkazu a check používají jazyk filtrů (Where):
remaining < minimum
daysOverdue >= 3 and reminderLevel < 1
partner.labels.code in ('VIP', 'PARTNER')
labels.code = 'BEZ-UPOMINEK'
note is null
name like 'servis' // obsahuje
code begins 'ZB'
isWorkday = false
total > 100000 and (costCenter.code = 'MKT' or branch.code = 'PRAHA')
-
Texty jsou v jednoduchých uvozovkách; čísla,
trueafalsebez nich. -
Vazba nebo seznam se čte přes tečku. U seznamu znamená
labels.code = 'VIP'„kterýkoli z nich“. -
Porovnání s neznámým (
null) faktem je nepravda; fakta pravidlo nikdy neshodí. -
${název}v podmínce se před čtením podmínky nahradí nastavením nebo parametrem:partner.labels.code in ('${companyLabels}'). -
Jména, která podmínka smí číst:
- fakta oblasti;
- u oblastí, které běží nad záznamy (automatizace, upomínky, schvalování), i pole a vazby záznamu;
- kalendář:
today,now,country,isWorkday,isHoliday; constsady, nastavení oblasti a parametry pravidla;letpravidla.
Jiné jméno se nahlásí jako
Unknown fact "x".
4. Hodnoty a zprávy
Hodnota set, argumenty do a hodnota let jsou výrazy:
| Tvar | Příklad |
|---|---|
| fakt, pole, nastavení | quantity, partner.code, minimum |
| text, číslo, pravdivostní hodnota | 'UPOMINKA-1', 11, true |
| aritmetika | quantity * 2, dueDate + 14, total - paid |
| funkce | roundup(quantity, 11) (nahoru na násobek), max(quantity, minimumQuantity), min(a, b) |
šablona (text s ${…}) |
"Objednávka ${code} je zaplacená", 'Upomínka ${number}' |
Zprávy check a else ask jsou šablony: "Objednávka u ${supplier.name} za ${orderTotal} je nad limitem".
5. Fakta pravidla: let
| Tvar | Význam |
|---|---|
let rest = total - paid |
výraz nad fakty |
let lastPrice = lookup purchasePrices[product_id = '${product.id}'].price |
jedno pole prvního záznamu entity, který odpovídá filtru (server ho načte předem) |
let score = script 'return facts.quantity * 2' |
JavaScript v izolovaném prostředí (QuickJS): vidí jen fakta, žádnou síť ani čas; vrací JSON |
let suspicious = ai boolean "Je popis faktury neobvyklý?" using description, partner.name |
otázka na AI: boolean, number nebo text. Jen v bězích na pozadí a podle pravidel posílání dat AI; fakt, který se poslat nesmí, se nepošle a odpověď je neznámá |
6. Spouštěče: on:
on: mají jen oblasti se spouštěči (automatizace); ostatní oblasti spouští aplikace (při uložení, každý den, na stránce
objednávání, …).
on: saved
on: created, deleted
on: changed isPaid to true
on: changed status from 'new' to 'confirmed'
on: event 'paid'
on: schedule daily
on: manual
- Více spouštěčů se odděluje čárkou. Pravidlo bez
on:přebírá spouštěče nadřazeného; pravidlo, nad kterým žádnéon:není, se spouští při každém spouštěči. - Události:
paid(platba byla spárována),sent(zpráva o záznamu byla odeslána),fromInbox(doklad vznikl z doručené pošty). - V automatizaci jsou k dispozici fakta
previous.<pole>(hodnota před změnou) achanged.<pole>(true, když změna pole změnila).
7. Hotová pravidla, nastavení a parametry
Systémové sady obsahují hotová pravidla: pravidla s id, popisem, default: on|off a nastaveními, která používají.
Firma je zapíná a vypíná a vyplňuje jejich nastavení; ukládá se jen tato volba (jako aktivace), nikdy text. Vlastní
pravidla se píšou do vlastních sad stejné oblasti a běží po systémových.
## Velké částky
> Nad nastavenou částku schvaluje vedoucí střediska, jeho nadřízený a pak jednatel.
id: large
default: off
when: total > largeAmount
do requireApproval by costCenter.manager then by costCenter.manager.superior then by role '${directorRole}'
Parametr pravidla: param <název>: <typ> [= <výchozí>] ["<popisek>"]. Typy jsou:
number,money,days,text,template;code <entita>,codes <entita>,where <entita>;enum(a, b, c).
Parametr se používá jako ${název} nebo jen jménem.
param tolerance: money = 1 "Tolerance"
param labels: codes labels = 'VIP' "Štítky"
8. Příklady podle oblastí
Příjem dokladů: dohledání produktu řádku
## Hledání produktu podle kódů
id: codes
lines: try product by ean
lines: try product by packageEan
lines: try product by supplierCode
lines: else ask "Vyberte nebo založte produkt pro ${name}"
Nákup: množství podle balení, podezřelá objednávka
## Množství podle dodavatele
id: packages
set quantity = roundup(max(quantity, minimumQuantity), packageQuantity)
## Podezřelá objednávka
id: suspicious
check orderTotal <= suspiciousOrder else block "Objednávka u ${supplier.name} za ${orderTotal} je nad limitem – zkontrolujte ji"
Schvalování: malé částky bez schvalování, změněný bankovní účet účetní
## Malé částky bez schvalování
id: small
when: total <= 5000
do approve
stop
## Změněný bankovní účet
id: account
when: bankAccountChanged = true
do requireApproval by role 'UCETNI'
stop
Automatizace: zaplacená objednávka dostane úkol pro sklad
## Zaplacená objednávka
id: paid
on: changed isPaid to true
do createTask 'Vyskladnit ${code}' for 'role:SKLAD'
9. Chyby
Parser a oblast hlásí každý problém s číslem řádku:
| Chyba | Příčina |
|---|---|
A single # heading is the title of the rulebook; nodes start at ## |
druhý nadpis # |
Heading level skipped |
#### přímo pod ## |
`when:` belongs to a node, after its heading |
řádek pravidla před prvním ## |
Condition "…": … |
podmínka není platný filtr |
Expression "…": … |
hodnota není platný výraz |
The id "x" is used twice |
dvě pravidla se stejným id: |
Unknown fact "x"; expected … |
jméno, které oblast nemá (překlep, nebo fakt jiné oblasti) |
check expects `check <where> else block|error|warning|info "<message>"` |
chybí část else nebo uvozovky zprávy |
`try` expects `try <target> by <resolver> …` |
chybí by |