# 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       |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.tokeninc.com/token-developer-portal-1/x-platform/baslangic/horeca.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
