table.close_aborted · packet.close_aborted — kapanış düştü ✓ Canlı

Gate akışında eklenti önce sorulur, kapanış sonra yürütülür. Mali bir eklenti allow dediği anda fişi imzalamış olabilir; iki adım arasında hesaba bir kalem ya da ödeme eklenirse kapanış ön koşulu bozulur ve reddedilir. Bu olay o dar pencerenin telafisidir: geldiğinde kestiğin fişi storno et. Masa ve paket kanalında birebir aynı sözleşme.

← Event Kataloğu · Gate (Hook) akışı

Canlı — masa ve paket kanalında yayında. table.close_aborted ve packet.close_aborted aynı sözleşmeyi taşır; mali eklentiysen ikisine birden abone ol — tek handler ikisini de karşılar.

Neden var — imzaladın ama kapanış olmadı

  1. panel → gate sorusu           (table.close)
  2. eklenti → allow               ← MALİ FİŞ BURADA İMZALANIR
  ─── dar pencere: masaya kalem/ödeme eklenirse ön koşul bozulur ───
  3. closeTable → REDDEDER         (underpaid / overpaid / …)
  4. platform → table.close_aborted ← TELAFİ: fişini storno et

Mali bir eklenti allow dediği anda fişi imzalamış olur. Kapanış bu adımdan sonra yürütüldüğü için aradaki dar pencerede masaya bir kalem veya ödeme eklenirse ön koşul bozulur ve closeTable reddeder → mali izinde fişi kesilmiş, POS'ta hâlâ açık bir satış kalır. Bu olay o durumu size bildirir.

Yalnız gate gerçekten çalıştıysa yayınlanır. İstek gateTokens taşımıyorsa imzalanmış bir fiş de yoktur → sinyal üretilmez.

Payload

Gövde table.updated ile aynı kanonik şekildedir (kapanış denemesi anındaki son hâl); üzerine tek alan eklenir.

table.close_aborted
{
  "id": "evt_<uuid>",
  "type": "table.close_aborted",
  "version": "1",
  "actor": { "type": "staff" },
  "environment": "sandbox",
  "tenantId": "<tenantId>",
  "occurredAt": 1786930000000,
  "sequence": 12,
  "sequenceScope": "sq_9f3ab27c",
  "data": {
    "tableId": "masa-401",
    "uuid": "2434d66d-3d59-41a8-bf83-feba7d8086b1",
    "abortReason": "underpaid",
    "orders": [ "… kapanış denemesi anındaki tam liste …" ],
    "payments": [ "…" ],
    "cancels": [ "…" ],
    "total": 271.17,
    "paid": 250,
    "currency": "TRY",
    "amountExponent": 2
  }
}

Paket kanalında tek fark gövdenin paket şekli olmasıdır — packet.updated ile aynı kanonik şekil + abortReason. Sebep sözlüğü, sıra kuralı ve tüketici davranışı birebir aynıdır.

packet.close_aborted
{
  "id": "evt_<uuid>",
  "type": "packet.close_aborted",
  "version": "1",
  "actor": { "type": "staff" },
  "environment": "sandbox",
  "tenantId": "<tenantId>",
  "occurredAt": 1786930000000,
  "sequence": 9,
  "sequenceScope": "sq_2c14d8e0",
  "data": {
    "packetId": "pkt-9931",
    "uuid": "9f3c1a7e-4b21-4c8e-9a55-7f2b1d0e6c31",
    "abortReason": "underpaid",
    "orders": [ "… kapanış denemesi anındaki tam liste …" ],
    "payments": [ "…" ],
    "cancels": [ "…" ],
    "total": 271.17,
    "paid": 250,
    "currency": "TRY",
    "amountExponent": 2
  }
}

data.abortReason değerleri

abortReasonNe olduSenin tarafında
underpaidTahsilat borcun altında kaldıFişi storno et; personel tahsilatı tamamlayıp yeniden kapatacak
overpaidTahsilat borcu aştıFişi storno et; fazla tahsilat kabul edilmiyor
payment_without_orderÖdeme var, kalem yokFişi storno et
total_repairedtotal kalemlerle tutmuyordu; sunucu düzeltti ve kapanışı reddettiFişi storno et; düzeltilmiş tutarla yeni kapanış gelecek
Liste büyüyebilir: tanımadığın bir abortReason görürsen de iptal say (fişi storno et) — olay zaten "kapanış düştü" demektir. Olayı düşürme.

İptal, kapanışın tersi DEĞİLDİR

Defterini kapatma. Satış hattı sürüyor: aynı sequenceScope, sequence artmadan (kapanış gerçekleşmediği için sayaç ilerlemez). Hesabı açık say ve aynı satışın devamını bekle — düzeltilmiş tutarla yeni bir kapanış denemesi gelecek.
Tüketici tarafı
// Handler — dördü de aynı sonucu doğurur: KESTİĞİN FİŞİ STORNO ET.
// Masa ve paket AYNI sözleşme → tek dal ikisini de karşılar.
case 'table.close_aborted':
case 'packet.close_aborted': {
  await ledger.reverse(accountKey(envelope.data));   // 1) fişi storno et (anahtar: uuid — bkz. accountKey)

  // 2) DEFTERİNİ KAPATMA: satış hattı sürüyor (aynı sequenceScope, sequence ARTMADAN)
  //    → hesabı AÇIK say, düzeltilmiş yeni kapanış denemesini bekle.
  store.set(accountKey(envelope.data), envelope.data);
  break;
}
// ⚠️ Tanımadığın bir abortReason gelirse de İPTAL say — olay zaten "kapanış düştü" demektir.

İki kanal, tek sözleşme

Paket karşılığı da yayınlanıyor. packet.close_aborted birebir aynı sözleşmedir: aynı gerekçe, aynı abortReason sözlüğü, aynı sıra kuralı, aynı "yalnız gate çalıştıysa" koşulu. Paket kapanışı da token yolunu desteklediği için dar pencere pakette de açılıyor → ikisine birden abone ol; tek bir handler ile karşılayabilirsin.
AlanTipZorunluAçıklama
Ön koşul kapısıilgili–Kapanamayacak bir hesap için gate hiç çalıştırılmaz ve plugin.hook.preconditionFailed döner — imzalanmış ama karşılığı olmayan fiş üretimini baştan engeller. Bu kapı stale okumaya dayanır; nihai karar kapanış anındaki taze okumadır → aradaki dar pencere bu olayla kapatılır.
data.uuidstring | null–Satışın ömürlük kimliği — storno edeceğin kaydı bununla bul (doküman kimliği tableId kapanış/geri açmada değişir, uuid değişmez).

Abonelik

Manifest: events: ["table.close_aborted"] + events:subscribe. Veri kapsamı orders:read. Gate'i zaten çalıştırdığın için pratikte hooks:table.close ile birlikte kullanılır.