> For the complete documentation index, see [llms.txt](https://developer.tokeninc.com/token-developer-portal-1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.tokeninc.com/token-developer-portal-1/x-platform/baslangic/horeca.md).

# HoReCa

**Önemli Noktalar**

1. **Get Fiscal Parameters ZORUNLUDUR:** Sepet oluşturmadan önce `terminal-id` ile Get Fiscal Parameters API çağrılması ve dönen sectionNo/taxPercent değerleri MUTLAKA kullanılmalıdır.
2. **Kablosu entegrasyonda Polling YAPILMAZ, Webhook ZORUNLUDUR:** Sepet durumu kontrol etmek için setInterval/polling kullanamazsınız. Set Client Settings API ile webhook tanımlayın.
3. **sectionNo Ataması OKC Cihazında Tanımlanır:** API'ye gönderilen sectionNo değerleri, OKC cihazında önceden Setup edilmiş mali kısımlarla eşleşmeli. Fiscal Parameters API bu değerleri döndürür.
4. **basketID Benzersiz Olmalıdır:** Her sepet için UUID v4 kullanın. Sabit veya tahmin edilebilir ID'ler sepetlerin karışmasına neden olur.

***

#### Tek Fişte Farklı KDV

**Soru:** Aşağıdaki sepet doğru mu? Özellikle `taxPercent` değerleri ve `sectionNo` ataması onaylanmak isteniyor?

```json
{
  "basketID": "masa-12-2025-04-11",
  "documentType": 0,
  "items": [
    {"name": "Izgara Köfte",  "price": 32000, "sectionNo": 2, "taxPercent": 1000, "quantity": 1000},
    {"name": "Efes Bira 0.5", "price": 18000, "sectionNo": 1, "taxPercent": 2000, "quantity": 2000}
  ],
  "paymentItems": [{"amount": 78000, "type": 1}]
}
```

**✅ CEVAP**

**Sepet yapısı DOĞRU**, ancak aşağıdaki hususlara dikkat edilmeli:

1. **sectionNo Değerleri:** Örnekteki `sectionNo` atamalarının (1=alkol%20, 2=yiyecek%10) OKC cihazında fiziksel olarak tanımlanmış olması gerekir. Bunları doğrulamak için:

   ```typescript
   // Sepet oluşturmadan ÖNCE yapılmalı:
   const fiscalParams = await getFiscalParams(terminalId);
   console.log(fiscalParams.sections);
   // Output örneği:
   // [
   //   { sectionNo: 1, taxPercent: 2000, name: "İçecek - Alkollü" },
   //   { sectionNo: 2, taxPercent: 1000, name: "Yiyecek" },
   //   { sectionNo: 3, taxPercent: 2000, name: "Servis Bedeli" }
   // ]
   ```
2. **taxPercent FORMAT:** Değerler **temel puan** formatında gönderilir (100 = %1, 1000 = %10, 2000 = %20). Örnekteki değerler doğru.
3. **Tutar Hesaplaması:**
   * Izgara Köfte: 32.000 TL (sectionNo 2, %10 KDV) → Toplam tutara %10 katkı
   * Bira: 36.000 TL (18×2, sectionNo 1, %20 KDV) → Toplam tutara %20 katkı
   * Servis: 10.000 TL (sectionNo 3, %20 KDV) → Toplam tutara %20 katkı
   * **Toplam:** 78.000 TL ✓
4. **Sectionno: 3 Ayrı Kısım mı?**
   * ✅ **EVET, ayrı olmalıdır.** Servis bedeli yiyecek kalemine dahil edilirse Türkiye'de vergi ziyaı oluşur.
   * Restoranlar TÜRe göre sectionNo: 3'ü "Garsoniye / Servis Bedeli" olarak setup ederler.
   * Bu kurulum **OKC cihazında yapılır** (Setup > Sections), API'de değil.

**Doğru Kod Yapısı**

```typescript
async function buildRestaurantBasket(tableId: string, items: CartItem[], paymentAmount: number): Promise<Basket> {
  // Adım 1: Terminal ID'den Fiscal Parameters al
  const fiscalInfo = await getFiscalParams(terminalId);
  
  // Adım 2: Sectionları doğrula
  const alcoholSection = fiscalInfo.sections.find(s => s.name.includes("Alkol"));
  const foodSection = fiscalInfo.sections.find(s => s.name.includes("Yiyecek"));
  const serviceSection = fiscalInfo.sections.find(s => s.name.includes("Servis"));
  
  // Adım 3: Sepet oluştur
  const basket: Basket = {
    basketID: uuid(),
    documentType: 0,
    items: [
      { 
        name: "Izgara Köfte", 
        price: 32000, 
        sectionNo: foodSection.sectionNo, 
        taxPercent: foodSection.taxPercent, 
        quantity: 1000 
      },
      { 
        name: "Efes Bira 0.5", 
        price: 18000, 
        sectionNo: alcoholSection.sectionNo, 
        taxPercent: alcoholSection.taxPercent, 
        quantity: 2000 
      },
      { 
        name: "Servis Bedeli", 
        price: 10000, 
        sectionNo: serviceSection.sectionNo, 
        taxPercent: serviceSection.taxPercent, 
        quantity: 1000 
      }
    ],
    paymentItems: [{ amount: 78000, type: 1 }] // Nakit
  };
  
  return basket;
}
```

**Token Dokümantasyon Referansı**

* **Get Fiscal Parameters API:** `GET /v1/fiscal-info?terminal-id={terminalId}`
* **Yanıt örneği:**

  ```json
  {
    "status": 0,
    "result": {
      "sections": [
        { "sectionNo": 1, "taxPercent": 2000, "name": "İçecek - Alkollü" },
        { "sectionNo": 2, "taxPercent": 1000, "name": "Yiyecek" },
        { "sectionNo": 3, "taxPercent": 2000, "name": "Servis Bedeli" }
      ]
    }
  }
  ```

***

#### Hesap Bölme (Split Bill): Tek Masada 3 Farklı Ödeme

**Soru:** Bir masadaki ödeme 3 parça yapılacaksa 3 ayrı sepet arka arkaya OKC'ye gönderilebilir mi? Aynı masa/oturum için zincirleme sepet gönderiminde herhangi bir kısıt var mı?

**✅ CEVAP**

**Arka arkaya sepet göndermede bir kısıt yoktur ancak işlemlerin karışmadan parçalı ödenebilmesi için doğrudan ÖKC üzerinde parçalı ödeme akışı kullanılmalıdır.**

Tek bir sepet OKC'ye gönderilir, parçalama ve tahsilat adımları cihaz üzerinde yapılır. Ödemeler tamamlandığında entegrasyon tarafına webhook ile ödeme bilgileri döner.

**Tek Sepet ile Parçalı Ödeme (ÖNERILEN AKIŞ)**

```typescript
async function handleSplitBillOnDevice(
  tableId: string,
  allItems: CartItem[],
  customerCount: number
): Promise<SplitBillResult> {
  // Tek bir sepet oluştur — tüm ürünleri içerir
  const basket: Basket = {
    basketID: uuid(),
    documentType: 0,
    items: allItems.map(item => ({
      name: item.name,
      price: item.price,
      sectionNo: item.sectionNo,
      taxPercent: item.taxPercent,
      quantity: item.quantity
    })),
    paymentItems: [
      {
        // Ödeme miktarını henüz net belirleme - cihazda yapılacak
        amount: allItems.reduce((sum, item) => sum + item.price, 0),
        type: 2  // Placeholder
      }
    ]
  };
  
  // Sepeti gönder
  const sendResult = await addBasket(basket, terminalId);
  
  // OKC cihazında müdür/kasiyer:
  // 1. "Hesap Böl" seçeneğini tıklar
  // 2. Müşteri sayısını girer (3)
  // 3. Her müşteri için ödeme yöntemi seçer (kart/nakit)
  // 4. Cihaz ödeme işlemlerini tamamlar
  
  // Webhook — Her ödeme parçası için gönderilir
  return {
    basketID: basket.basketID,
    status: "awaiting_split_payments",
    message: "ÖKC cihazında parçalı ödeme başlatıldı. Ödemeler webhook ile bildirilecek."
  };
}
```

**Webhook: Parçalı Ödemeler**

```json
// Webhook — Ödemeler tamamlandığında
{
  "operation": "BASKET_COMPLETED",
  "data": {
    "basketID": "split-001-uuid",
    "status": 0,
    "paymentItems": [
      { "amount": 35200, "type": 3 },
      { "amount": 19800, "type": 1 },
      { "amount": 24000, "type": 3 }
    ],
    "receiptNo": "00001",
    "zNo": "123456"
  }
}
```

**Bu Akışın Avantajları**

* ✅ OKC cihazının native split bill özelliğini kullanır
* ✅ Sistem kompleksliğini azaltır
* ✅ Tüm ödemeler tek basketID altında konsolide edilir
* ✅ Müdür/kasiyer dostu (cihaz üzerinde "Hesap Böl" butonu)
* ✅ Audit trail daha temiz

***

#### İkramı / Bedelsiz Ürün

**Soru A:** Ürünü sepete 0 fiyatlı kalem olarak eklemek mümkün mü?\
**Soru B:** Gerçek fiyatı yazıp indirim kalemi eklemek mümkün mü?\
**Soru C:** Toplam tutarı 0 TL olan bir sepet OKC'ye gönderilebilir mi?

**✅ CEVAPLAR**

| Soru                           | Cevap          | Açıklama                                                                     |
| ------------------------------ | -------------- | ---------------------------------------------------------------------------- |
| **A - 0 TL Kalem**             | ⚠️ ÖNERILMEZ   | Patron ikramı için doğrudan 0 TL kalem yerine indirim akışı kullanılmalıdır. |
| **B - Gerçek fiyat + indirim** | ✅ EVET         | Tutar indirimi olarak %100 indirim gönderebilirsiniz.                        |
| **C - Uygulama yöntemi**       | ✅ `adjust` ile | `discount` objesinde `type` ve `value/totalValue` iletilmelidir.             |

**Önerilen Yöntem**

Patron ikramı için ürün gerçek fiyatıyla kalır, indirim `item.adjust` üzerinden gönderilir.

`Discount` objesindeki `"type": 0` ve `"value"` alanını tek ürün fiyatı olarak iletebilirsiniz.

Ürün quantity'si 1'den fazla ise `item.adjust` içinde `"value"` yerine `"totalValue"` göndererek birim fiyata değil tüm ürünlere uygulanacak indirimi iletebilirsiniz.

**JSON Örnekleri**

**3 adet kolanın birim fiyatına 100 TL indirim**

```json
{
  "basketID": "83998e84-c68d-47a3-af56-449f5650baa1",
  "checkNumber": 1,
  "paymentItems": [
    {
      "description": "NAKİT",
      "amount": 15000,
      "type": 1
    }
  ],
  "items": [
    {
      "name": "Pizza",
      "price": 15000,
      "sectionNo": 1,
      "taxPercent": 100,
      "quantity": 1000
    },
    {
      "name": "Cola",
      "price": 10000,
      "sectionNo": 1,
      "taxPercent": 100,
      "quantity": 3000,
      "adjust": {
        "description": "Item Discount",
        "discountOrSurcharge": 0,
        "type": 0,
        "value": 10000
      }
    }
  ]
}
```

**3 adet kolanın tamamına 300 TL indirim**

```json
{
  "basketID": "83998e84-c68d-47a3-af56-449f5650baa1",
  "checkNumber": 1,
  "paymentItems": [
    {
      "description": "NAKİT",
      "amount": 15000,
      "type": 1
    }
  ],
  "items": [
    {
      "name": "Pizza",
      "price": 15000,
      "sectionNo": 1,
      "taxPercent": 100,
      "quantity": 1000
    },
    {
      "name": "Cola",
      "price": 10000,
      "sectionNo": 1,
      "taxPercent": 100,
      "quantity": 1000,
      "adjust": {
        "description": "Item Discount",
        "discountOrSurcharge": 0,
        "type": 1,
        "totalValue": 30000
      }
    }
  ]
}
```

**Not**

Patron ikramı senaryosunda ana yaklaşım: `item.adjust` ile indirim göndermek, kalemi sıfırlamak yerine mali izlenebilirliği korumaktır.

***

#### Kart ile Bahşiş

**Soru A:** Bahşiş OKC fişine dahil edilmeli mi?\
**Soru B:** Dahil edilecekse hangi kısıma, hangi KDV oranıyla?\
**Soru C:** `paymentItems` toplamı `items` toplamını aşabilir mi?

**✅ CEVAPLAR**

Kredi kartı ile bahşiş için resmi yaklaşım şu an geliştirme aşamasındadır.

***

#### Yemek Çeki / TokenFlex / Sodexo / Multinet / Edenred

**Soru:** Yemek çeki ödemesi `paymentItems` içinde hangi `type` kodu ile iletilmeli?

**Çözüm: Yemek Çekini Kart (Type 7) Olarak Gönder**

```typescript
// Yemek çekini Sodexo kartı gibi kart ödeme olarak gönder
const basket: Basket = {
  basketID: uuid(),
  documentType: 0,
  items: [...],
  paymentItems: [
    {
      amount: foodCheckAmount,  // Çek tutar
      type: 7  // Yemek kartı olarak kodla
    },
    {
      amount: remainingAmount,  // Çekin kapsamadığı (alkol gibi)
      type: 1  // Nakit ile tamamla
    }
  ]
};
```

***

#### Büyük Masa Kurumsal Fatura (Tutar > 12.000 TL)

**Soru:** İşyeri kendi e-fatura sisteminde 2 ayrı KDV oranı içeren fatura kesiyor, sonra OKC'ye E-Fatura Bilgi Fişi (documentType:9006) gönderiyor. Bilgi fişindeki `items` listesi e-fatura ile birebir eşleşmeli mi, yoksa sadece toplam tutar yeterli mi?

**✅ CEVAP**

**Items listesi e-fatura ile BİREBİR eşleşmeli. Sadece toplam yeterli DEĞİL.**

Token OKC, E-Fatura Bilgi Fişi (documentType: 9006) gönderildiğinde, aşağıdaki doğrulamalar yapar:

1. **KDV Tutarı Doğrulaması:** Gönderilen items'den hesaplanan KDV, e-faturadaki KDV ile eşit olmalı
2. **Tutar Doğrulaması:** Items toplamı, birebir eşleşmeli
3. **KDV Kısımları (sectionNo):** Farklı oranlar farklı kısımlar MUTLAKA ayrılmalı

**Doğru Davranış**

```
İşyerin e-Faturası:
├─ Yemek & İçecek: 200 TL (KDV %10 = 20 TL)
└─ Alkol: 80 TL (KDV %20 = 16 TL)
   Toplam Tutar: 280 TL + KDV 36 TL = 316 TL

↓ (Aynı detay) ↓

OKC'ye Gönderilen Sepet (documentType: 9006):
{
  "items": [
    {"name": "Yemek & İçecek", "price": 200000, "sectionNo": 2, "taxPercent": 1000},
    {"name": "Alkollü İçecek", "price": 80000, "sectionNo": 1, "taxPercent": 2000}
  ],
  "paymentItems": [{"amount": 31600, "type": 1}]
}
```

**Kod Yapısı**

```typescript
interface InvoiceDetail {
  description: string;
  amount: number;           // Tutar (kuruş)
  taxRate: number;         // KDV oranı (100 = %1, 1000 = %10, 2000 = %20)
  sectionNo: number;
}

function buildCorporateInvoiceBasket(
  invoiceNo: string,
  invoiceDetails: InvoiceDetail[],
  customerTaxId: string,
  customerName: string
): Basket {
  const fiscalInfo = getFiscalParams(terminalId);
  
  // Items listesini e-fatura ile eşleştir
  const items = invoiceDetails.map(detail => {
    const section = fiscalInfo.sections.find(s => s.taxPercent === detail.taxRate);
    
    if (!section) {
      throw new Error(
        `E-fatura KDV oranı ${detail.taxRate / 100}% OKC'de tanımlanmamış.`
      );
    }
    
    return {
      name: detail.description,
      price: detail.amount,
      sectionNo: section.sectionNo,
      taxPercent: section.taxPercent,
      quantity: 1000
    };
  });
  
  // KDV kontrol
  const totalKdv = items.reduce((sum, item) => {
    return sum + (item.price * item.taxPercent / 100000);
  }, 0);
  
  const totalAmount = items.reduce((sum, item) => sum + item.price, 0) + totalKdv;
  
  const basket: Basket = {
    basketID: uuid(),
    documentType: 9006, // E-Fatura Bilgi Fişi
    customerInfo: {
      taxID: customerTaxId,
      name: customerName
    },
    infoReceiptInfo: {
      serialNo: invoiceNo  // E-fatura sistem tarafından üretilen seri no
    },
    items: items,
    paymentItems: [
      {
        amount: totalAmount,
        type: 1 // Nakit
      }
    ]
  };
  
  return basket;
}
```

**JSON Örneği (Onerilen Örnekten Düzeltilmiş)**

```json
{
  "basketID": "kurumsal-2025-00456-uuid",
  "documentType": 9006,
  "customerInfo": {
    "taxID": "9876543210",
    "name": "XYZ Holding A.Ş."
  },
  "infoReceiptInfo": {
    "serialNo": "GIB2025000087654"
  },
  "items": [
    {
      "name": "Yemek & İçecek",
      "price": 2000000,
      "sectionNo": 2,
      "taxPercent": 1000,
      "quantity": 1000
    },
    {
      "name": "Alkollü İçecek",
      "price": 800000,
      "sectionNo": 1,
      "taxPercent": 2000,
      "quantity": 1000
    }
  ],
  "paymentItems": [
    {
      "amount": 2800000,
      "type": 1 // Nakit
    }
  ]
}
```

**Dikkat: documentType: 9006 Şartları**

* **İşyeri:** E-fatura mükellefi OLMALI
* **Müşteri:** E-fatura mükellefi OLMALI (B2B)
* **Tutar:** Genellikle > 12.000 TL
* **E-Fatura Sistemi:** İşyerin e-fatura platformunda fatura önceden oluşturulmuş OLMALI
* **Seri Numarası:** `GIB` veya `ARGS` başlayan belge numarası

Eğer müşteri kurumsal değilse → documentType: 9007 (E-Arşiv Bilgi Fişi)

***

#### Otel Minibar ve Oda Servisi (Çoklu Gelir Merkezi)

**Soru A:** Farklı günlerde farklı gelir merkezlerinde oluşan harcamalar check-out sırasında tek bir sepette birleştirilerek OKC'ye gönderilebilir mi?\
**Soru B:** Her gelir merkezi için ayrı kısım (sectionNo) gerekiyor mu? Otel için önerilen kısım yapısı nedir?

**✅ CEVAPLAR**

| Soru                    | Cevap  | Detay                                                                 |
| ----------------------- | ------ | --------------------------------------------------------------------- |
| **A - Konsolide Sepet** | ✅ EVET | Farklı gelir merkezlerinden harcamalar tek sepette birleştirilebilir. |
| **B - Ayrı sectionNo**  | ✅ EVET | Her gelir merkezi (minibar, oda servisi, SPA) ayrı sectionNo almalı.  |

**Otel Kısım Yapısı (Önerilen)**

```json
{
  "sections": [
    {
      "sectionNo": 1,
      "name": "Konaklama",
      "taxPercent": 2000,
      "description": "Oda ücretleri, gecelik"
    },
    {
      "sectionNo": 2,
      "name": "Restoran",
      "taxPercent": 1000,
      "description": "Otel restoranından yiyecek"
    },
    {
      "sectionNo": 3,
      "name": "Bar - Alkol",
      "taxPercent": 2000,
      "description": "Bar ve koktail servisi"
    },
    {
      "sectionNo": 4,
      "name": "Minibar",
      "taxPercent": 2000,
      "description": "Oda minibarı harcamaları"
    },
    {
      "sectionNo": 5,
      "name": "SPA / Wellness",
      "taxPercent": 2000,
      "description": "Spa, masaj, fitness hizmetleri"
    },
    {
      "sectionNo": 6,
      "name": "Oda Servisi",
      "taxPercent": 1000,
      "description": "Room service meals"
    }
  ]
}
```

**Code Yapısı**

```typescript
interface HotelChargeRecord {
  date: string;              // ISO 8601 (2025-04-14)
  revenueCenter: "dining" | "minibar" | "spa" | "room-service" | "accommodation";
  description: string;
  amount: number;
  taxRate: number;
}

function buildHotelCheckoutBasket(
  guestName: string,
  roomNumber: string,
  chargeRecords: HotelChargeRecord[]
): Basket {
  const fiscalInfo = getFiscalParams(terminalId);
  
  // Tarih aralığını belirle
  const dates = chargeRecords.map(r => new Date(r.date));
  const checkInDate = new Date(Math.min(...dates.map(d => d.getTime())));
  const checkOutDate = new Date(Math.max(...dates.map(d => d.getTime())));
  
  // İtem listesini oluştur
  const items = chargeRecords.map(charge => {
    let sectionNo: number;
    let sectionName: string;
    
    switch (charge.revenueCenter) {
      case "dining":
        sectionNo = 2;
        sectionName = "Restoran";
        break;
      case "minibar":
        sectionNo = 4;
        sectionName = "Minibar";
        break;
      case "spa":
        sectionNo = 5;
        sectionName = "SPA";
        break;
      case "room-service":
        sectionNo = 6;
        sectionName = "Oda Servisi";
        break;
      default:
        sectionNo = 1;
        sectionName = "Konaklama";
    }
    
    const section = fiscalInfo.sections.find(s => s.sectionNo === sectionNo);
    
    return {
      name: `${charge.date} - ${sectionName}: ${charge.description}`,
      price: charge.amount,
      sectionNo: section.sectionNo,
      taxPercent: section.taxPercent,
      quantity: 1000
    };
  });
  
  const totalAmount = items.reduce((sum, item) => sum + item.price, 0);
  
  const basket: Basket = {
    basketID: uuid(),
    documentType: 0,  // Veya > 12.000 TL ise 9007
    items: items,
    paymentItems: [
      {
        amount: totalAmount,
        type: 1  // Nakit / oda hesabı
      }
    ]
  };
  
  return basket;
}
```

**JSON Örneği**

```json
{
  "basketID": "hotel-checkout-room-512-uuid",
  "documentType": 0,
  "items": [
    {
      "name": "2025-04-11 - Konaklama: Oda 512 (1 Gece)",
      "price": 500000,
      "sectionNo": 1,
      "taxPercent": 2000,
      "quantity": 1000
    },
    {
      "name": "2025-04-11 - Minibar: Su, Bira x2",
      "price": 45000,
      "sectionNo": 4,
      "taxPercent": 2000,
      "quantity": 1000
    },
    {
      "name": "2025-04-12 - Oda Servisi: Breakfast Tray",
      "price": 68000,
      "sectionNo": 6,
      "taxPercent": 1000,
      "quantity": 1000
    },
    {
      "name": "2025-04-13 - SPA: Masaj (60 min)",
      "price": 120000,
      "sectionNo": 5,
      "taxPercent": 2000,
      "quantity": 1000
    }
  ],
  "paymentItems": [
    {
      "amount": 733000,
      "type": 1
    }
  ]
}
```

***

#### Etkinlik Kaparosu ve Bakiye Tahsilatı

**Soru:** Adım 2'de düzenlenen e-Arşiv fişindeki toplam tutar, kaparo tutarını dahil mi etmeli, hariç mi tutmalı? Bakiye hesabı fatura numarasına mı yoksa basketID'ye mi bağlanıyor?

**✅ CEVAP**

| Konusunda                    | Cevap & Açıklama                                                                             |
| ---------------------------- | -------------------------------------------------------------------------------------------- |
| **Kaparo Tutar Dahil mi?**   | ✅ **Adım 2'de HARIÇ tutulmalı.** Sepet toplamı = Tamam Hizmet Tutarı (kaparo YOK).           |
| **Bakiye Hesabı Bağlantısı** | **basketID'ye bağlanmalı** (veritabanı tutucu) ve referans olarak fatura no'su kullanılmalı. |

**Süreç Detayları**

**Adım 1: Kaparo (documentType: 9000)**

```json
{
  "basketID": "dugun-kaparo-2025-089-uuid",
  "documentType": 9000,
  "customerInfo": {
    "name": "Mehmet & Ayşe Yılmaz",
    "taxID": "12345678901"
  },
  "taxFreeAmount": 5000000  // 50.000 TL kaparo
}
```

**Kaydedilecek:**

* basketID: `dugun-kaparo-2025-089-uuid`
* Müşteri: Mehmet & Ayşe Yılmaz
* Kaparo Tutarı: 50.000 TL
* Bulamış Tutar: 0 TL (kaparo sadece ayrılır)

**Adım 2: Etkinlik Günü — Ana Fiş (documentType: 9007)**

```json
{
  "basketID": "dugun-etkinlik-2025-089-uuid",
  "documentType": 9007,
  "customerInfo": {
    "name": "Mehmet & Ayşe Yılmaz",
    "taxID": "12345678901"
  },
  "infoReceiptInfo": {
    "serialNo": "ARS2025000089000"
  },
  "items": [
    // Burada YALNIZCA etkinlik sezes harcaması
    {
      "name": "Düğün Yemeği Hizmeti (120 Kişi)",
      "price": 170000000,  // 1.700.000 TL = 170 milyar kuruş
      "sectionNo": 2,
      "taxPercent": 1000,
      "quantity": 1000
    }
  ],
  "paymentItems": [
    {
      "amount": 170000000,
      "type": 17  // Açık hesap
    }
  ]
}
```

**Kaydedilecek:**

* basketID: `dugun-etkinlik-2025-089-uuid`
* Referans: dugun-kaparo-2025-089 (kaparo için)
* Fiş Tutarı: 1.700.000 TL (kaparo HARİÇ)
* Fatura No: ARS2025000089000

**Adım 3: Bakiye Tahsilatı (documentType: 9002)**

```json
{
  "basketID": "dugun-bakiye-2025-089-uuid",
  "documentType": 9002,
  "customerInfo": {
    "name": "Mehmet & Ayşe Yılmaz",
    "taxID": "12345678901"
  },
  "infoReceiptInfo": {
    "documentDate": "11-07-2025",
    "documentNo": "GIB2025000089000"
  },
  "taxFreeAmount": 1200000000,  // 1.200.000 TL bakiye
  "paymentItems": [
    {
      "amount": 1200000000,
      "type": 1  // Nakit
    }
  ]
}
```

**Kaydedilecek:**

* basketID: `dugun-bakiye-2025-089-uuid`
* Referans: dugun-etkinlik-2025-089 (ana fiş için)
* Bakiye Tutarı: 1.200.000 TL
* Hesaplandı: 1.700.000 TL (Adım 2) + 50.000 TL (kaparo) - 550.000 TL (arzu edilen ek harç) = toplam

**Kod Yapısı**

```typescript
interface EventReservation {
  reservationId: string;
  customerName: string;
  taxId: string;
  totalContractAmount: number; // Tüm hizmet tutarı
  depositAmount: number;
}

interface EventCheckout {
  reservation: EventReservation;
  eventDate: string;
  eventServiceAmount: number; // Gerçek hizmet tutarı (kaparo YOK)
  additionalCharges?: number;
  paymentMethod: number;
}

async function handleEventCatering(event: EventCheckout) {
  // Adım 1: Kaparo (önceden yapılmış farz edilsin)
  const depositBasket = {
    basketID: `event-deposit-${event.reservation.reservationId}-uuid`,
    documentType: 9000,
    customerInfo: {
      name: event.reservation.customerName,
      taxID: event.reservation.taxId
    },
    taxFreeAmount: event.reservation.depositAmount * 100
  };
  
  const depositResult = await addBasket(depositBasket, terminalId);
  // Kaparo basketID'sini kaydet
  
  // Adım 2: Etkinlik Günü — Ana Fiş
  const eventBasket = {
    basketID: `event-main-${event.reservation.reservationId}-uuid`,
    documentType: 9007,
    customerInfo: {
      name: event.reservation.customerName,
      taxID: event.reservation.taxId
    },
    infoReceiptInfo: {
      serialNo: generateInvoiceNumber() // ARS2025...
    },
    items: [
      {
        name: `${event.eventDate} - Etkinlik Hizmeti`,
        price: event.eventServiceAmount * 100,
        sectionNo: 2,
        taxPercent: 1000,
        quantity: 1000
      }
    ],
    paymentItems: [
      {
        amount: event.eventServiceAmount * 100,
        type: 17 // Açık hesap
      }
    ]
  };
  
  const eventResult = await addBasket(eventBasket, terminalId);
  
  // Adım 3: Bakiye Tahsilatı
  const remainingBalance = event.eventServiceAmount + 
                          (event.additionalCharges || 0) - 
                          event.reservation.depositAmount;
  
  const balanceBasket = {
    basketID: `event-balance-${event.reservation.reservationId}-uuid`,
    documentType: 9002,
    customerInfo: {
      name: event.reservation.customerName,
      taxID: event.reservation.taxId
    },
    infoReceiptInfo: {
      documentDate: new Date().toLocaleDateString('tr-TR'),
      documentNo: generateBalanceReceiptNumber()
    },
    taxFreeAmount: remainingBalance * 100,
    paymentItems: [
      {
        amount: remainingBalance * 100,
        type: event.paymentMethod
      }
    ]
  };
  
  const balanceResult = await addBasket(balanceBasket, terminalId);
  
  return {
    depositBasketId: depositResult.basketID,
    eventBasketId: eventResult.basketID,
    balanceBasketId: balanceResult.basketID
  };
}
```

**Önemli: Tutar Hesaplaması**

```
┌─────────────────────────────────────────┐
│ Sözleşme: 2.050.000 TL                 │
├─────────────────────────────────────────┤
│ Adım 1 (Kaparo):         50.000 TL    │ ← Sadece bloke, ödeme DEĞİL
│                                        │
│ Adım 2 (Etkinlik Fiş):  1.700.000 TL  │ ← Kaparo HARİÇ
│         KDV: 170.000 TL                │
│                                        │
│ Adım 3 (Bakiye Tahsilat): 300.000 TL  │ ← 1.700.000 + 50.000 - 1.450.000 ödenen
│                                        │
│ TOPLAM ÖDEME: 2.000.000 TL             │ ← Kaparo + Bakiye
└─────────────────────────────────────────┘
```

***

#### Referans: Fiscal Parameters Yapısı

Sepet oluşturmadan ÖNCE çağrılması gereken Get Fiscal Parameters API'sinin döndürdüğü yapı:

```json
{
  "status": 0,
  "description": "Successfully Fetched Fiscal Parameters",
  "result": {
    "sections": [
      {
        "sectionNo": 1,
        "name": "İçecek - Alkollü",
        "taxPercent": 2000,
        "type": 0,
        "limit": 0,
        "price": 0,
        "plus": []
      },
      {
        "sectionNo": 2,
        "name": "Yiyecek & Alkolsüz İçecek",
        "taxPercent": 1000,
        "type": 0,
        "limit": 0,
        "price": 0,
        "plus": []
      },
      {
        "sectionNo": 3,
        "name": "Servis Bedeli",
        "taxPercent": 2000,
        "type": 0,
        "limit": 0,
        "price": 0,
        "plus": []
      }
    ],
    "terminal": "AV0000000658",
    "createdAt": "2025-03-20T13:51:06.961Z",
    "updatedAt": "2025-03-20T13:51:06.961Z"
  }
}
```

***

#### Özet: Kritik Kurallar

| Kural                            | Şart                    | Hata Kodu            |
| -------------------------------- | ----------------------- | -------------------- |
| **Get Fiscal Parameters MUTLAK** | Sepet oluşturmadan önce | 400 - Kısım yok      |
| **Unique basketID**              | UUID v4 kullanın        | 409 - Çokluk         |
| **Polling YASAK**                | Webhook kullanın        | 429 - Rate limit     |
| **LOCKED sepet güncelleme**      | Güncelleme yapılmaz     | 422 - Kilitli        |
| **documentType doğru seçim**     | Tutar bazında otomatik  | 400 - Yanlış type    |
| **Webhook MUTLAK**               | Ödeme sonucu alınır     | Sonuç alınamaz       |
| **Items = sectionNo'ye ait**     | Fiscal params'ten al    | 400 - Hatalı section |
| **KDV dahil fatura eşiği**       | 12.000 TL (2026)        | Fiş reddedilir       |
