Disko API'si (Nakitsiz Kulüp)¶
Disko modülü, tamamen nakitsiz yürütülen bir kulüp/disko işletmesini temsil eder: Her misafir girişte, tüm süre boyunca bir hesap görevi gören bir kart (çip/RFID/NFC) alır. Her şey — giriş, içecekler, vestiyer, masa siparişleri — karta kaydedilir ve ancak ayrılırken (veya ön ödemeli yüklemeyle) hesaplanır. API, bir kartın tüm yaşam döngüsünü kapsar: girişe al → kaydet → yükle → hesapla → çıkışa izin ver.
Tüm uç noktalar ortak api/v1/disco ön ekinin altındadır (bu ön eki üç denetleyici paylaşır:
Misafirler/Kartlar, İstatistikler, Yapılandırma — artı api/v1/disco/turnstile altındaki turnike
donanımı API'si). Tüm alanlarda olduğu gibi: JWT Bearer, yanıt zarfı
{ "success": true, "data": { ... } }, camelCase alanlar, opak kimlikler.
Disko modülünü gerektirir
Disko modülünü gerektirir; aktif bir modül lisansı olmadan uç noktalar HTTP 403
döner (errorCode: "MODULE_NOT_LICENSED").
Kart kimliği ile dahili kimlik
Her kayıtta dahili bir id (veritabanı anahtarı) ve bir guestId bulunur — bu, çipin fiziksel
olarak üzerine yazıldığı kart numarasıdır. Tüm {cardId} rotaları dahili id'yi değil,
guestId'yi bekler.
Misafirler ve Kartlar¶
DiscoController — Temel api/v1/disco:
| Yöntem | Uç Nokta | Amaç |
|---|---|---|
POST |
/enter |
Misafiri turnikede içeri alma (giriş kart taraması) |
POST |
/leave |
Misafiri ödeme ile çıkışa alma (çıkış taraması) |
POST |
/leave-combined |
Birden fazla kartı („çift") ortak bir belgede hesaplama ve kapatma |
POST |
/book |
Karta ürün kaydetme (bar/tezgâh) |
POST |
/book/batch |
Karta birden fazla ürünü aynı anda kaydetme |
POST |
/book/{guestId}/{bonIndex}/void |
Kaydedilen kalemi iptal etme |
POST |
/table/book-on-card |
Masa siparişini karta kaydetme (masa ödemesinin yerini alır) |
POST |
/wardrobe/return/{guestId}/{bonIndex} |
Vestiyer iadesi (numarayı kaldırır, tutar kalır) |
GET |
/guest/{cardId} |
Misafir/kart, güncel ciro dahil (yalnızca açık kartlar) |
GET |
/guest/{cardId}/status |
Kart durumu, kilitli/iptal edilmiş/hesaplanmış dahil |
GET |
/guest/{cardId}/checkout |
Hesaplama görünümü: açık tutar, ön ödeme karşılığı, çıkabilir mi |
GET |
/guests |
Şu anda mevcut olan (giriş yapmış) tüm misafirler |
POST |
/guest/{cardId}/topup |
Ön ödemeli bakiye yükleme |
POST |
/guest/{cardId}/transfer |
Kartı/bakiyeyi başka bir karta aktarma (kart değişimi) |
POST |
/guest/{cardId}/lock |
Kartı kilitleme (artık kayıt yapılamaz) |
POST |
/guest/{cardId}/unlock |
Kartın kilidini açma |
POST |
/guest/{cardId}/storno |
Kartın tamamını iptal etme + ödeme yapmayan olarak işaretleme |
POST |
/guest/{cardId}/collect-storno |
İptal edilmiş kartı kasada sonradan tahsil etme |
POST |
/guest/{cardId}/image |
Kart fotoğrafı ekleme |
POST |
/terminal/pay |
Bilgi terminalinde self servis kart ödemesi başlatma |
POST |
/personal/{cardId}/close |
Bir personel kartını hesaplama (öz tüketim) |
POST |
/personal/close-all |
Tüm açık personel kartlarını öz tüketim olarak hesaplama |
POST |
/close-all |
Tüm açık kartları kapatma (işletme kapanışı/gün sonu raporu) |
Karta kaydetme¶
POST /api/v1/disco/book, açık bir karta bir ürün kaydeder (ödemesiz bar/tezgâh satışı — ödeme
ancak leave/çıkışta gerçekleşir).
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"
}
Yanıt (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 }
]
}
}
Kart durumu¶
GET /api/v1/disco/guest/{cardId}/status, kartın hâlâ açık olup olmadığından bağımsız olarak
durumu döner — yalnızca açık kartları bulan GET /guest/{cardId}'den farklı olarak. Böylece
bar/vestiyer/kasa, kilitli veya iptal edilmiş kartları da tanır.
{
"success": true,
"data": {
"found": true,
"isOpen": true,
"isLocked": false,
"stornoed": false,
"guest": { "id": "dgu_9f8e7d", "guestId": "crd_10042", "amount": 7.00, "uploadAccount": 20.00 }
}
}
Güncel ciro¶
GET /api/v1/disco/guest/{cardId}, yukarıdakiyle aynı DiscoGuestResponse'u, devam eden açık
kayıtlar (openBons) ve ön ödemeli bakiye (uploadAccount) dahil olarak döner. Kart (artık) açık
değilse yanıt 404 GUEST_NOT_FOUND olur.
Hesaplama/Çıkış¶
GET /api/v1/disco/guest/{cardId}/checkout hiçbir şeyi değiştirmez — kartın hâlâ ne borçlu
olduğunun, ön ödemeli bakiyenin neyi karşıladığının ve otomatik olarak çıkıp çıkamayacağının
(self-checkout, mobil çıkış kasası, turnike) salt bir önizlemesidir.
{
"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 €"
}
}
status, ok | pay | locked | closed | notfound değerlerinden biridir.
Karta masa¶
POST /api/v1/disco/table/book-on-card, bir masanın açık kalemlerini bir Disko kartına aktarır
(Disko masa modu) — masadaki nakit/kart ödemesinin yerini alır, kart limitleri geçerliliğini
korur, masa boşalır.
openBonIds: null, tüm açık kalemleri aktarır; bir liste yalnızca bir „Sofort" (anlık) turunu
aktarır.
Yükleme¶
POST /api/v1/disco/guest/{cardId}/topup, kartın ön ödemeli bakiyesini (uploadAccount) yükler —
tutar serbestçe seçilebilir, kalan bakiye çıkışta iade edilir.
Yanıt yine güncellenmiş DiscoGuestResponse'dur (uploadAccount artırılmış).
Karıştırma riski: Disko kart bakiyesi ile müşteri hesabı bakiyesi
Burada söz konusu olan, tek bir Disko ziyaretinin kart ön ödemesidir (ayrılışta biter/iade edilir). Kalıcı bir müşteri hesabı bakiyesi ise ayrı bir kavramdır — bkz. Müşteri Hesabı: Bakiye ve Puanlar.
İstatistikler¶
DiscoStatsController — Temel api/v1/disco:
| Yöntem | Uç Nokta | Amaç |
|---|---|---|
GET |
/stats |
Canlı göstergeler (ciro, mevcut misafirler, gruba/çalışma yerine/personele/saate göre doluluk) |
GET |
/search |
Kart/misafir arama (kart numarası, ad, dönem, cinsiyet, iptal filtresi, sayfalama) |
GET |
/personal/{ownerId}/activity |
Bir personel kartının etkinliği (tüketim, iptal, kayıp/fire) |
GET |
/daylog/{date} |
Bir tarih için gün protokolü |
Örnek: 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 } ]
}
}
GET /search, diğerlerinin yanı sıra cardId, name, dateFrom/dateTo, gender,
timeFrom/timeTo, workplaceId, enterGroupId, wardrobe, stornoed, offset/limit,
excludeImages parametrelerini destekler.
Yapılandırma¶
DiscoConfigController — Temel api/v1/disco, giriş/fiyat grupları için klasik CRUD
(„Entergroups" — ör. giriş ücreti, kart limiti, ücretsiz içecekler, minimum tüketim belirler):
| Yöntem | Uç Nokta | Amaç |
|---|---|---|
GET |
/entergroups |
Tüm giriş grupları |
GET |
/entergroups/{id} |
Tek bir giriş grubu |
POST |
/entergroups |
Giriş grubu oluşturma |
PUT |
/entergroups/{id} |
Giriş grubunu güncelleme |
DELETE |
/entergroups/{id} |
Giriş grubunu silme |
Turnike Donanımı¶
DiscoTurnstileController — api/v1/disco/turnstile/{key}/{cardId} (GET/POST).
JWT yok — kimlik doğrulama URL içindeki API anahtarı ({key}) ile yapılır, böylece basit
bir turnike kumandası rotayı bir giriş akışı olmadan çağırabilir. 200 = kart çıkabilir, diğer tüm
kodlar bir neden taşır (kilitli/açık/zaten hesaplanmış/bilinmiyor/yanlış anahtar).
→ Ayrıntılar, kurulum ve durum kodu tablosu: Disko Turnikesi.
Uçtan Uca Akış¶
Tipik bir misafir akışı, tüm adımlar crd_10042 üzerinden:
TOKEN="eyJ..."
API="https://ihre-instanz.dikas.de/api/v1"
# 1. Einlass am Drehkreuz (Kartenscan Eingang)
curl -X POST "$API/disco/enter" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{ "guestId": "crd_10042", "gender": 1, "enterGroupId": "eg_std" }'
# 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": [ { "method": "Cash", "amount": 0 } ] }'
Arıza durumu — kart çıkışta ödeme yapamıyor (ödeme yapmayan misafir):
# 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 } ] }'