feat: /objednani – skupinové objednávky s QR platbou
CI / Generate TypeScript types (push) Successful in 18s
CI / Generate TypeScript types (pull_request) Successful in 9s
CI / Server unit tests (push) Successful in 21s
CI / Build client (push) Successful in 40s
CI / Server unit tests (pull_request) Successful in 21s
CI / Build server (pull_request) Successful in 24s
CI / Build server (push) Has been cancelled
CI / Playwright E2E tests (push) Has been cancelled
CI / Build and push Docker image (push) Has been cancelled
CI / Notify (push) Has been cancelled
CI / Build client (pull_request) Has been cancelled
CI / Playwright E2E tests (pull_request) Has been cancelled
CI / Build and push Docker image (pull_request) Has been cancelled
CI / Notify (pull_request) Has been cancelled

Nahrazuje /vecere novou stránkou /objednani. Místo jednoho
OBJEDNAVAM bucketu umožňuje vytvářet více skupin, kde každá
objednává z jiného obchodu.

- Skupiny mají stavový automat: open → locked → ordered
- Obchody spravuje admin heslem (ADMIN_PASSWORD env var)
  přes modal „Správa obchodů"
- Při stavu ordered zakladatel generuje QR kódy platby
  (nový PayForGroupModal – volné částky bez menu)
- PayForAllModal (oběd) upraven: plátce nyní vidí svůj
  vlastní díl jako informační řádek
- Nové testy: stores.test.ts + groups.test.ts (36 testů)
This commit is contained in:
2026-05-07 07:05:01 +02:00
parent 774be3df6d
commit 936b33cc80
28 changed files with 1641 additions and 242 deletions
+22
View File
@@ -81,6 +81,28 @@ paths:
/changelogs:
$ref: "./paths/changelogs/getChangelogs.yml"
# Skupiny objednávek (/api/groups)
/groups/create:
$ref: "./paths/groups/createGroup.yml"
/groups/delete:
$ref: "./paths/groups/deleteGroup.yml"
/groups/addMember:
$ref: "./paths/groups/addMember.yml"
/groups/removeMember:
$ref: "./paths/groups/removeMember.yml"
/groups/updateMember:
$ref: "./paths/groups/updateMember.yml"
/groups/setState:
$ref: "./paths/groups/setState.yml"
# Správa obchodů (/api/stores)
/stores:
$ref: "./paths/stores/listStores.yml"
/stores/add:
$ref: "./paths/stores/addStore.yml"
/stores/delete:
$ref: "./paths/stores/deleteStore.yml"
# DEV endpointy (/api/dev)
/dev/generate:
$ref: "./paths/dev/generate.yml"
+21
View File
@@ -0,0 +1,21 @@
post:
operationId: addGroupMember
summary: Přidá uživatele do skupiny (sebe, nebo jiného jako zakladatel).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
properties:
id:
description: ID skupiny
type: string
login:
description: Login uživatele (volitelné — pokud není zadán, přidá přihlášeného uživatele)
type: string
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+18
View File
@@ -0,0 +1,18 @@
post:
operationId: createGroup
summary: Vytvoří novou skupinu objednávky pro aktuální den.
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
description: Název obchodu/restaurace (musí být v seznamu povolených obchodů)
type: string
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+18
View File
@@ -0,0 +1,18 @@
post:
operationId: deleteGroup
summary: Smaže skupinu objednávky (pouze zakladatel).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
properties:
id:
description: ID skupiny
type: string
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+22
View File
@@ -0,0 +1,22 @@
post:
operationId: removeGroupMember
summary: Odebere uživatele ze skupiny (sebe, nebo jiného jako zakladatel).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
- login
properties:
id:
description: ID skupiny
type: string
login:
description: Login uživatele k odebrání
type: string
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+21
View File
@@ -0,0 +1,21 @@
post:
operationId: setGroupState
summary: Změní stav skupiny (pouze zakladatel).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
- state
properties:
id:
description: ID skupiny
type: string
state:
$ref: "../../schemas/_index.yml#/GroupState"
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+34
View File
@@ -0,0 +1,34 @@
post:
operationId: updateGroupMember
summary: Aktualizuje data člena skupiny (částka, poznámka, příplatek).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- id
- login
properties:
id:
description: ID skupiny
type: string
login:
description: Login člena ke změně
type: string
amount:
description: Částka k úhradě v Kč
type: number
note:
description: Poznámka
type: string
surchargeText:
description: Popis příplatku
type: string
surchargeAmount:
description: Výše příplatku v Kč
type: number
responses:
"200":
$ref: "../../api.yml#/components/responses/ClientDataResponse"
+28
View File
@@ -0,0 +1,28 @@
post:
operationId: addStore
summary: Přidá obchod do seznamu povolených (vyžaduje admin heslo).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- heslo
properties:
name:
description: Název obchodu/restaurace
type: string
heslo:
description: Admin heslo (ADMIN_PASSWORD)
type: string
responses:
"200":
description: Obchod byl přidán
content:
application/json:
schema:
type: array
items:
type: string
+28
View File
@@ -0,0 +1,28 @@
post:
operationId: deleteStore
summary: Odebere obchod ze seznamu povolených (vyžaduje admin heslo).
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- heslo
properties:
name:
description: Název obchodu/restaurace k odebrání
type: string
heslo:
description: Admin heslo (ADMIN_PASSWORD)
type: string
responses:
"200":
description: Obchod byl odebrán
content:
application/json:
schema:
type: array
items:
type: string
+12
View File
@@ -0,0 +1,12 @@
get:
operationId: listStores
summary: Vrátí seznam povolených obchodů/restaurací.
responses:
"200":
description: Seznam obchodů
content:
application/json:
schema:
type: array
items:
type: string
+72
View File
@@ -66,6 +66,16 @@ ClientData:
slot:
description: Slot jídla, ke kterému se tato data vztahují
$ref: "#/MealSlot"
groups:
description: Skupiny objednávajících pro extra slot
type: array
items:
$ref: "#/OrderGroup"
stores:
description: Seznam povolených obchodů/restaurací pro extra objednávky
type: array
items:
type: string
# --- OBĚDY ---
UserLunchChoice:
@@ -674,6 +684,68 @@ ClearMockDataRequest:
description: Index dne v týdnu (0 = pondělí, 4 = pátek). Pokud není zadán, použije se aktuální den.
$ref: "#/DayIndex"
# --- SKUPINOVÉ OBJEDNÁVKY ---
GroupState:
description: Stav skupiny objednávky
type: string
enum:
- open
- locked
- ordered
x-enum-varnames:
- OPEN
- LOCKED
- ORDERED
OrderGroupMember:
description: Data člena skupiny objednávky
type: object
additionalProperties: false
properties:
amount:
description: Částka k úhradě v Kč
type: number
note:
description: Volitelná poznámka (např. co si objednává)
type: string
surchargeText:
description: Popis příplatku
type: string
surchargeAmount:
description: Výše příplatku v Kč
type: number
OrderGroup:
description: Skupina uživatelů objednávajících z jednoho místa
type: object
additionalProperties: false
required:
- id
- name
- creatorLogin
- state
- members
properties:
id:
description: Unikátní identifikátor skupiny
type: string
name:
description: Název obchodu/restaurace
type: string
creatorLogin:
description: Login zakladatele skupiny
type: string
state:
$ref: "#/GroupState"
members:
description: Členové skupiny
type: object
additionalProperties:
$ref: "#/OrderGroupMember"
tipTotal:
description: Celkové dýško (Kč), vyplněno při přechodu do stavu ordered
type: number
# --- NEVYŘÍZENÉ QR KÓDY ---
PendingQr:
description: Nevyřízený QR kód pro platbu