Diszkó-API (készpénzmentes klub)¶
A Disco modul egy teljesen készpénzmentesen működő klub-/diszkóüzemet képez le: minden vendég a beléptetéskor kap egy kártyát (chip/RFID/NFC), amely a teljes ott-tartózkodás alatt számlaként szolgál. Mindent — belépőt, italokat, ruhatárat, asztali rendeléseket — a kártyára könyvelnek, és csak távozáskor (vagy előre fizetett feltöltéssel) számolnak el. Az API egy kártya teljes életciklusát lefedi: beléptetés → könyvelés → feltöltés → elszámolás → távozás.
Minden végpont a közös api/v1/disco előtag alatt található (három vezérlő osztozik ezen az
előtagon: vendégek/kártyák, statisztikák, konfiguráció — ezen felül a forgókapu-hardver API a
api/v1/disco/turnstile alatt). Mint minden területen: JWT-Bearer, válaszboríték
{ "success": true, "data": { ... } }, camelCase mezők, átlátszatlan azonosítók.
A Disco modult igényli
A Disco modult igényli; aktív modullicenc nélkül a végpontok HTTP 403 választ adnak
(errorCode: "MODULE_NOT_LICENSED").
Kártyaazonosító és belső azonosító
Minden adatrekordnak van egy belső id értéke (adatbázis-kulcs) és egy guestId értéke — ez a
kártyaszám, amellyel a chip fizikailag fel van címkézve. Minden {cardId} útvonal a
guestId értéket várja, nem a belső id értéket.
Vendégek és kártyák¶
DiscoController — alap: api/v1/disco:
| Metódus | Végpont | Cél |
|---|---|---|
POST |
/enter |
Vendég beléptetése a forgókapunál (kártyabeolvasás a bejáratnál) |
POST |
/leave |
Vendég kiléptetése fizetéssel (beolvasás a kijáratnál) |
POST |
/leave-combined |
Több kártya („pár") közös elszámolása és lezárása egy bizonylaton |
POST |
/book |
Termék könyvelése a kártyára (bár/pult) |
POST |
/book/batch |
Több termék könyvelése egyszerre a kártyára |
POST |
/book/{guestId}/{bonIndex}/void |
Könyvelt tétel sztornózása |
POST |
/table/book-on-card |
Asztali rendelés könyvelése a kártyára (kiváltja az asztali fizetést) |
POST |
/wardrobe/return/{guestId}/{bonIndex} |
Ruhatári kiadás (eltávolítja a #számot, az összeg megmarad) |
GET |
/guest/{cardId} |
Vendég/kártya az aktuális forgalommal együtt (csak nyitott kártyák) |
GET |
/guest/{cardId}/status |
Kártyaállapot, letiltott/sztornózott/elszámolt kártyák esetén is |
GET |
/guest/{cardId}/checkout |
Elszámolási nézet: nyitott összeg, előre fizetett fedezet, távozhat-e |
GET |
/guests |
Minden jelenleg jelen lévő (beléptetett) vendég |
POST |
/guest/{cardId}/topup |
Előre fizetett egyenleg feltöltése |
POST |
/guest/{cardId}/transfer |
Kártya/egyenleg átvitele másik kártyára (kártyacsere) |
POST |
/guest/{cardId}/lock |
Kártya letiltása (további könyvelés nem lehetséges) |
POST |
/guest/{cardId}/unlock |
Kártya feloldása |
POST |
/guest/{cardId}/storno |
Teljes kártya sztornózása + nem fizetőként való megjelölése |
POST |
/guest/{cardId}/collect-storno |
Sztornózott kártya utólagos beszedése a pénztárnál |
POST |
/guest/{cardId}/image |
Kártyafotó rögzítése |
POST |
/terminal/pay |
Önkiszolgáló bankkártyás fizetés indítása az információs terminálon |
POST |
/personal/{cardId}/close |
Egy személyzeti kártya elszámolása (saját fogyasztás) |
POST |
/personal/close-all |
Minden nyitott személyzeti kártya elszámolása saját fogyasztásként |
POST |
/close-all |
Minden nyitott kártya lezárása (üzemzárás/napi zárás) |
Beléptetés opcionális egyenlegfeltöltéssel¶
A POST /api/v1/disco/enter egy névtelen vendégkártya esetén a belépőt és a kártya további
előre fizetett egyenlegét egyetlen folyamatban szedheti be. A topUpAmount opcionális, alapértéke 0.
POST /api/v1/disco/enter
Authorization: Bearer eyJ...
Content-Type: application/json
{
"guestId": "crd_10042",
"gender": 1,
"enterGroupId": "eg_std",
"workplaceId": "wp_entry",
"topUpAmount": 20.00,
"payments": [
{ "method": "Cash", "amount": 30.00 }
]
}
A fizetéseknek együtt kell fedezniük a belépőt és a feltöltést. Egy bizonylat keletkezik, külön
tételekkel: a belépő normál adózású forgalomként, a feltöltés 0 %-os kötelezettségként. Az
uploadAccount csak a bizonylat sikeres könyvelése után nő. Megengedett érték 0 és 10000
között; ügyfél- és személyzeti kártyák esetén a beléptetéskori feltöltést a rendszer elutasítja:
| Hibakód | Jelentés |
|---|---|
DISCO_ENTRY_TOPUP_CUSTOMER_NOT_ALLOWED |
Az ügyfélkártyákat az ügyfélszámlán keresztül kell feltölteni |
DISCO_ENTRY_TOPUP_PERSONAL_NOT_ALLOWED |
A személyzeti kártyák beléptetéskor nem kapnak névtelen kártyaegyenleget |
Könyvelés a kártyára¶
A POST /api/v1/disco/book egy terméket könyvel egy nyitott kártyára (bár/pult értékesítés
fizetés nélkül — a fizetés csak a leave/checkout során történik).
POST /api/v1/disco/book
Authorization: Bearer eyJ...
Content-Type: application/json
{
"guestId": "crd_10042",
"articleId": "art_cola",
"articleName": "Cola 0,3l",
"count": 2,
"price": 3.50,
"workplaceId": "wp_bar1",
"workplaceName": "Bar 1"
}
Válasz (200 OK, DiscoGuestResponse):
{
"success": true,
"data": {
"id": "dgu_9f8e7d",
"guestId": "crd_10042",
"gender": 1,
"enterDate": "2026-07-12T22:05:00Z",
"amount": 7.00,
"payedAmount": 0,
"uploadAccount": 20.00,
"iou": 0,
"isOpen": true,
"isLocked": false,
"openBons": [
{ "articleId": "art_cola", "articleName": "Cola 0,3l", "price": 3.50, "count": 2, "total": 7.00,
"workplaceId": "wp_bar1", "workplaceName": "Bar 1", "bookDate": "2026-07-12T23:10:00Z", "isVoided": false }
]
}
}
Kártyaállapot¶
A GET /api/v1/disco/guest/{cardId}/status az állapotot attól függetlenül adja vissza, hogy a
kártya még nyitott-e — ellentétben a GET /guest/{cardId} hívással, amely csak nyitott kártyákat
talál. Így a bár, a ruhatár és a pénztár a letiltott vagy sztornózott kártyákat is felismeri.
{
"success": true,
"data": {
"found": true,
"isOpen": true,
"isLocked": false,
"stornoed": false,
"guest": { "id": "dgu_9f8e7d", "guestId": "crd_10042", "amount": 7.00, "uploadAccount": 20.00 }
}
}
Aktuális forgalom¶
A GET /api/v1/disco/guest/{cardId} ugyanazt a DiscoGuestResponse választ adja, mint fent,
a folyamatban lévő nyitott könyvelésekkel (openBons) és az előre fizetett egyenleggel
(uploadAccount) együtt. A válasz 404 GUEST_NOT_FOUND, ha a kártya nem (már nem) nyitott.
Elszámolás/checkout¶
A GET /api/v1/disco/guest/{cardId}/checkout semmit sem módosít — puszta előnézet arról, mennyivel
tartozik még a kártya, mennyit fedez az előre fizetett egyenleg, és automatikusan távozhat-e
(önkiszolgáló checkout, mobil kijárati pénztár, forgókapu).
{
"success": true,
"data": {
"cardId": "crd_10042",
"found": true,
"isOpen": true,
"isLocked": false,
"consumption": 7.00,
"netOwed": 7.00,
"prepaid": 20.00,
"amountToPay": 0,
"refund": 13.00,
"canAutoSettle": true,
"status": "ok",
"message": "Karte kann raus — Restguthaben 13.00 €"
}
}
A status értéke a következők egyike: ok | pay | locked | closed | notfound.
Ha egy névtelen kártyán több a prepaid, mint a netOwed, a többletet a kiszolgáló pénztár
készpénzben kifizeti. A lezáró kérés ehhez payoutExcess: true értéket ad meg; a fizetési lista
üres lehet:
Beállított kifizetési módban a háttérrendszer ezen jelölés nélkül DISCO_PAYOUT_REQUIRED hibával
megakadályozza a normál lezárást. A kártya ekkor nyitva marad, és nem keletkezik bizonylat. A
bankkártyás kifizetés nem része a Disco-checkoutnak; a payoutExcess egy készpénzes kifizetést
dokumentál és könyvel a feltöltés ellenkönyveléseként.
Asztal a kártyára¶
A POST /api/v1/disco/table/book-on-card egy asztal nyitott tételeit egy Disco-kártyára helyezi át
(Disco-asztalmód) — kiváltja az asztalnál történő készpénzes/bankkártyás fizetést, a kártyalimitek
továbbra is érvényesek, az asztal felszabadul.
Az openBonIds: null minden nyitott tételt átvisz; egy lista csak egy „azonnali" kört visz át.
Feltöltés¶
A POST /api/v1/disco/guest/{cardId}/topup feltölti a kártya előre fizetett egyenlegét
(uploadAccount) — az összeg szabadon választható, a maradék egyenleget checkoutkor visszatérítik.
A válasz ismét a frissített DiscoGuestResponse (megnövelt uploadAccount).
Összetéveszthető: Disco-kártyaegyenleg és ügyfélszámla-egyenleg
Ez itt egyetlen Disco-látogatás kártyás előre fizetett egyenlege (távozáskor lejár/visszatérül). Az állandó ügyfélszámla-egyenleg önálló fogalom — lásd Ügyfélszámla: egyenleg és pontok.
Statisztikák¶
DiscoStatsController — alap: api/v1/disco:
| Metódus | Végpont | Cél |
|---|---|---|
GET |
/stats |
Élő mutatók (forgalom, jelen lévő vendégek, kihasználtság csoport/munkaállomás/személyzet/óra szerint) |
GET |
/search |
Kártyák/vendégek keresése (kártyaszám, név, időszak, nem, sztornószűrő, lapozás) |
GET |
/personal/{ownerId}/activity |
Egy személyzeti kártya tevékenysége (fogyasztás, sztornó, törés) |
GET |
/daylog/{date} |
Napi napló egy adott napra |
Példa: GET /api/v1/disco/stats
{
"success": true,
"data": {
"totalGuests": 214,
"currentGuests": 87,
"totalMale": 96,
"totalFemale": 118,
"totalRevenue": 4211.50,
"averageSpend": 19.68,
"byGroup": [ { "groupId": "eg_std", "groupName": "Standard", "count": 180, "revenue": 3500.00 } ],
"byWorkplace": [ { "workplaceId": "wp_bar1", "workplaceName": "Bar 1", "count": 400, "revenue": 2200.00 } ],
"byStaff": [ { "personalId": "per_1", "personalName": "Mo", "count": 120, "revenue": 900.00 } ],
"byHour": [ { "hour": 23, "count": 60, "revenue": 800.00 } ]
}
}
A GET /search többek között a következőket támogatja: cardId, name, dateFrom/dateTo, gender, timeFrom/timeTo,
workplaceId, enterGroupId, wardrobe, stornoed, offset/limit, excludeImages.
Konfiguráció¶
DiscoConfigController — alap: api/v1/disco, klasszikus CRUD a belépő-/árcsoportokhoz
(„Entergroups" — ezek határozzák meg pl. a belépő árát, a kártyalimitet, az ingyenes italokat, a minimális fogyasztást):
| Metódus | Végpont | Cél |
|---|---|---|
GET |
/entergroups |
Minden belépőcsoport |
GET |
/entergroups/{id} |
Egy belépőcsoport |
POST |
/entergroups |
Belépőcsoport létrehozása |
PUT |
/entergroups/{id} |
Belépőcsoport frissítése |
DELETE |
/entergroups/{id} |
Belépőcsoport törlése |
Forgókapu-hardver¶
api/v1/disco/turnstile/{cardId} (GET/POST) az X-Dikas-Turnstile-Key fejléccel —
ez az ajánlott mód. A régebbi api/v1/disco/turnstile/{key}/{cardId} út (kulcs az útvonalban)
továbbra is működik; ha egy eszköz mindkettőt küldi, a fejléc érvényes.
Nincs JWT — a hitelesítés API-kulccsal történik, hogy egy egyszerű forgókapu-vezérlő bejelentkezési folyamat nélkül is elérhesse az útvonalat. 200 = a kártya távozhat, minden más kód okot hordoz (letiltva/nyitott/már elszámolva/ismeretlen/hibás kulcs).
→ Részletek, beállítás és állapotkód-táblázat: Disco-forgókapu.
Teljes folyamat az elejétől a végéig¶
Egy tipikus vendégút, minden lépés a crd_10042 kártyára:
TOKEN="eyJ..."
API="https://ihre-instanz.dikas.de/api/v1"
# 1. Einlass am Drehkreuz (Kartenscan Eingang), hier mit 20 € Guthaben
curl -X POST "$API/disco/enter" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "guestId": "crd_10042", "gender": 1, "enterGroupId": "eg_std", "topUpAmount": 20.00, "payments": [ { "method": "Cash", "amount": 30.00 } ] }'
# 2. Status prüfen (z. B. Wiedereinlass nach kurzem Verlassen)
curl "$API/disco/guest/crd_10042/status" -H "Authorization: Bearer $TOKEN"
# 3. Prepaid aufladen
curl -X POST "$API/disco/guest/crd_10042/topup" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "amount": 20.00, "paymentMethod": "Bar" }'
# 4. An der Bar buchen (einzeln oder als Batch)
curl -X POST "$API/disco/book" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "guestId": "crd_10042", "articleId": "art_cola", "articleName": "Cola 0,3l", "count": 2, "price": 3.50 }'
# 5. Laufenden Umsatz abfragen
curl "$API/disco/guest/crd_10042" -H "Authorization: Bearer $TOKEN"
# 6. Tischbestellung auf die Karte buchen
curl -X POST "$API/disco/table/book-on-card" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "tableId": "tbl_12", "cardId": "crd_10042" }'
# 7. Vor dem Ausgang: Checkout-Vorschau
curl "$API/disco/guest/crd_10042/checkout" -H "Authorization: Bearer $TOKEN"
# 8. Verlassen mit Zahlung (falls noch etwas offen ist)
curl -X POST "$API/disco/leave" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "cardId": "crd_10042", "payments": [], "payoutExcess": true }'
A pénztárnál történő kezelést a Felhasználói kézikönyv Disco modulja írja le.
Üzemzavar — a kártyával a kijáratnál nem tudnak fizetni (nem fizető vendég):
# Karte stornieren: als Nichtzahler markieren, Verzehr als Schwund verbuchen
curl -X POST "$API/disco/guest/crd_10042/storno" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "reason": "Karte verloren" }'
# Später an der Kasse nachkassiert
curl -X POST "$API/disco/guest/crd_10042/collect-storno" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "payments": [ { "method": "Cash", "amount": 7.00 } ] }'