Skip to main content

FirsatGO POS Entegrasyonu — YEMEK (food) Sektörü Geliştirici Dokümanı

engine: food · kapsanan sektörler: restaurant, cafe, fast_food, bakery Bu doküman yalnız yemek sektörü sipariş/katalog farklarını anlatır. HMAC imza, idempotency, retry, para birimi (*_minor), tenant-izolasyon gibi ortak sözleşme kuralları için ana entegrasyon spesifikasyonuna (docs/POSYOU_INTEGRATION_SPEC.md) bakınız.

Genel Bakış

Yemek sektörü; restoran, kafe, fast-food ve fırın işletmelerinin sipariş akışını kapsar. FirsatGO talep ağıdır (Getir / Trendyol-GO konumu); siparişi POS sistemine FG → POS REST POST {posBase}/orders ile iletir ve durum güncellemelerini POS → FG integration/orders/:id/status ile geri alır. Yemek siparişinin ayırt edici yanı kalem-bazlı malzeme modifikasyonudur (eklenen / çıkarılan malzeme, ekstra ücret) ve siparişin mutfak hazırlık durumundan geçen state-machine'idir. Yemekte teslimatı restoran/işletme yönetir; bu yüzden sektöre-özel fulfillment{} bloğu gönderilmez.

Sipariş Yaşam-Döngüsü

Yemek state-machine'i hazırlık (mutfak) adımını içerir:

pending → confirmed → preparing → ready → on_the_way → delivered → completed
(+ payment_pending, cancelled)
DurumAnlam
pendingSipariş oluşturuldu, işletme henüz onaylamadı.
confirmedİşletme siparişi kabul etti.
preparingMutfak hazırlığı başladı (yemek hazırlanıyor).
readySipariş hazır (kurye/teslim-alma bekliyor).
on_the_wayTeslimata çıktı (yalnız delivery).
deliveredMüşteriye teslim edildi.
completedSipariş tamamlandı (kapandı).
payment_pendingÖdeme bekleniyor (tahsilat tamamlanmamış).
cancelledİptal edildi; cancellation_reason dolu olur (order.cancelled olayı).

POS → FG durum geri-bildirimi confirmed/preparing/ready/on_the_way/delivered/completed/cancelled değerlerini, siparişi order_id veya external_order_id ile eşleyerek gönderir.

Sektöre-Özel Sipariş Alanları

fulfillment{} — GÖNDERİLMEZ

Yemek sektöründe teslimat sorumluluğu restorandadır; fulfillment bloğu boş/null gelir. (Çiçek recipient/sender/card_note, tekel age_verified, market substitution gibi sektör-özel fulfillment alanları yemekte yoktur.) Yemekte sektör-özel bilgi tamamen items[] içindedir.

items[] — kalem + malzeme modifikasyonu

Her kalem temel alanlara ek olarak yemek-özel malzeme kırılımı ve satır finansalı taşır:

AlanTipAnlam
reference_idstringÜrün/kampanya referansı.
namestringÜrün adı.
typeproduct | campaignKalem türü.
quantitynumberAdet.
original_unit_pricenumber (+_minor)Orijinal/menü birim fiyatı.
pricenumber (+_minor)Orijinal birim fiyat alias'ı (satırlar ara-toplama tutarlı toplanır).
discounted_pricenumber (+_minor)Ürün-indirimli (tahsil edilen) birim fiyat.
extra_pricenumber (+_minor)Eklenen malzeme birim ücreti (per-unit; *quantity sayılır).
line_totalnumber (+_minor)original_unit_price × quantity + extra_price × quantity.
line_discountnumber (+_minor)Ürün/menü indirimi: (original − discounted) × quantity.
notesstring | nullKalem notu (müşteri ürün-notu — fiş "Ürün Notları").
selected_ingredients[]{name, group, extra_price}Siparişte seçili tüm malzemeler.
added_ingredients[]{name, group, extra_price}EKLENEN malzemeler (varsayılan-dışı seçilen).
removed_ingredients[]{name, group}ÇIKARILAN malzemeler (varsayılan ama seçilmemiş + müşterinin removable_ingredients'tan çıkardıkları).

Malzeme türetme kuralı (kaynak: ingredient_groups[].ingredients[] üzerindeki is_selected / is_default bayrakları):

  • EKLENEN = is_selected = true ve is_default = false (müşteri ekledi).
  • ÇIKARILAN = is_default = true ve is_selected = false (müşteri çıkardı). Ayrıca düz removed_ingredients (string adlar) listesi bununla birleştirilir (farklı kaynak → çift-sayım yok).
  • SEÇİLİ = is_selected = true olan tüm malzemeler.

table_number

type = dine_in (masada) siparişlerde masa numarası taşınır. Diğer tiplerde null.

Örnek (sektöre-özel alanlar)

{
"type": "delivery",
"table_number": null, // dine_in dışında null
"fulfillment": null, // YEMEK: gönderilmez
"items": [
{
"reference_id": "665f0a...",
"name": "Acılı Cheeseburger Menü",
"type": "product",
"quantity": 2,
"original_unit_price": 180.00,
"discounted_price": 162.00, // ürün-indirimli birim fiyat
"extra_price": 15.00, // eklenen malzeme birim ücreti (per-unit)
"line_total": 390.00, // 180×2 + 15×2
"line_discount": 36.00, // (180−162)×2
"notes": "Az pişmiş olsun", // kalem notu
"selected_ingredients": [
{ "name": "Cheddar", "group": "Peynir", "extra_price": 0 },
{ "name": "Ekstra Bacon", "group": "Ekstralar", "extra_price": 15.00 }
],
"added_ingredients": [
{ "name": "Ekstra Bacon", "group": "Ekstralar", "extra_price": 15.00 }
],
"removed_ingredients": [
{ "name": "Soğan", "group": "Sebzeler" }
]
}
]
}

Katalog / Ürün

Yemek ürünü katalog şekli (item_kind = "food_product"). FG → POS GET /catalog/products ile çekilir veya POS POST /catalog/products ile upsert eder. Yemeğe-özel/önemli alanlar:

AlanTipAnlam
namestringÜrün adı.
pricenumberMenü fiyatı.
discounted_pricenumberİndirim sonrası fiyat.
discount_percentagenumber (0–100)İndirim yüzdesi.
categoryrefKategori referansı.
images[]string[]Görsel URL'leri.
ingredients[]string[]İçindekiler.
allergens[]string[]Alerjenler.
removable_ingredients[]string[]Çıkarılabilir malzemeler (müşteri "Çıkarılacak Malzeme Tercihleri").
is_vegetarian / is_vegan / is_gluten_free / is_spicybooleanDiyet/özellik bayrakları.
caloriesnumberPorsiyon başı kalori.
nutrition{}{protein,carbs,fat,fiber,sugar,sodium}Besin değeri.
preparation_timenumber (dk)Hazırlık süresi.
min_order_quantity / max_order_quantitynumberMin/maks sipariş adedi (0 = sınırsız).
available_quantity / remaining_quantitynumberStok (0 = sınırsız).
variants[]{name, options[]{name, price_modifier, is_default}}Varyant/seçenekler (ör. boy).
ingredient_groups[]{group_name, selection_type(radio|checkbox|dropdown), is_required, min_selections, max_selections}Malzeme grupları — seçim kuralları.
ingredient_group_configurations[]{exclude_ingredients[], extra_ingredients[]{name, extra_price}}Grup-bazlı hariç tutulanlar + ekstra (ücretli) malzemeler.
is_featuredbooleanÖne çıkan ürün.

sector_attributes (barcode/sku/lot/expiry vb.) yemek için boş kalır — bunlar market/petshop gibi envanter-tabanlı sektörlere aittir.

Akış Notları

  • fulfillment yok: Yemek payload'unda sektör-özel fulfillment bekleme. Teslimatı restoran/işletme yönetir.
  • extra_price per-unit: Eklenen malzeme ücreti birim başınadır ve line_total'da × quantity ile çarpılır. qty > 1 ekstralı kalemlerde toplamı per-unit ölçekte hesapla; aksi halde ara-toplam eksik çıkar.
  • Malzeme iki kaynaktan birleşir: ingredient_groups türevli çıkarılanlar + düz removed_ingredients string listesi → tek removed_ingredients[] (çift-sayım yok).
  • preparing = mutfak: Bu sektörde preparing durumu mutfakta hazırlanmayı ifade eder; ready hazır anlamına gelir. POS bu iki ayrı durumu doğru raporlamalı.
  • table_number: Yalnız dine_in siparişlerde dolu; delivery/pickup'ta null.
  • Finansal tutarlılık (kasa-fişi değişmezi): original_subtotal − discount_amount + (delivery_fee + service_fee + tip_amount + tax) = total, ve item_discount + additional_discount = discount_amount. original_subtotal orijinal fiyat toplamıdır; subtotal_charged ürün-indirimli sepet toplamıdır.
  • İptal: order.cancelled olayında cancellation_reason dolu gelir (top-level alandan veya son cancelled status_history girdisinden türetilir).

Örnek (gerçekçi sipariş payload — POST {posBase}/orders)

{
"order_id": "665fa1b2c3d4e5f600112233",
"order_number": "FG-2026-00482915",
"status": "confirmed",
"type": "delivery",
"cancellation_reason": null,

// ===== FİNANSAL KIRILIM (TRY; major + *_minor) =====
"original_subtotal": 405.00, "original_subtotal_minor": 40500,
"subtotal": 405.00,
"subtotal_charged": 369.00, "subtotal_charged_minor": 36900,
"item_discount": 36.00, "item_discount_minor": 3600,
"additional_discount": 20.00, "additional_discount_minor": 2000,
"discount_amount": 56.00, "discount_amount_minor": 5600,
"coupon_code": "ACILSEPET20",
"tax": 0, "tax_minor": 0,
"delivery_fee": 25.00, "delivery_fee_minor": 2500,
"service_fee": 0, "service_fee_minor": 0,
"tip_amount": 0, "tip_amount_minor": 0,
"total": 374.00, "total_minor": 37400,
"currency": "TRY", "currency_minor_unit": "kurus",

// ===== MÜŞTERİ =====
"customer": { "user_id": "660aabbccddeeff011223344", "name": "Burak E.", "phone": "+90555..." },

// ===== ADRES =====
"delivery_address": {
"street": "Bağdat Cad. No:12 D:5", "city": "İstanbul", "district": "Kadıköy",
"directions": "Kırmızı kapı, 2. kat, interkom 5", "name": "Burak E.", "phone": "+90555...",
"coordinates": { "latitude": 40.9876, "longitude": 29.0567 }
},
"delivery_directions": "Kırmızı kapı, 2. kat, interkom 5",
"table_number": null,

// ===== ÖDEME =====
"payment_method": "cash",
"payment_method_label": "Nakit",
"payment_status": "pending",

// ===== NOT + İLERİ TARİH =====
"notes": "Zile basmayın bebek uyuyor",
"scheduled_for": null,
"estimated_time": 35,

// ===== YEMEK: fulfillment gönderilmez =====
"fulfillment": null,

// ===== KALEMLER + MALZEME =====
"items": [
{
"reference_id": "665f0a11bb22cc33dd44ee55",
"name": "Acılı Cheeseburger Menü",
"type": "product",
"quantity": 2,
"original_unit_price": 180.00, "original_unit_price_minor": 18000,
"price": 180.00, "price_minor": 18000,
"discounted_price": 162.00, "discounted_price_minor": 16200,
"extra_price": 15.00, "extra_price_minor": 1500,
"line_total": 390.00, "line_total_minor": 39000,
"line_discount": 36.00, "line_discount_minor": 3600,
"notes": "Az pişmiş olsun",
"selected_ingredients": [
{ "name": "Cheddar", "group": "Peynir", "extra_price": 0 },
{ "name": "Ekstra Bacon", "group": "Ekstralar", "extra_price": 15.00 }
],
"added_ingredients": [
{ "name": "Ekstra Bacon", "group": "Ekstralar", "extra_price": 15.00 }
],
"removed_ingredients": [
{ "name": "Soğan", "group": "Sebzeler" }
]
},
{
"reference_id": "665f0a11bb22cc33dd44ee99",
"name": "Ayran",
"type": "product",
"quantity": 1,
"original_unit_price": 45.00, "original_unit_price_minor": 4500,
"price": 45.00, "price_minor": 4500,
"discounted_price": 45.00, "discounted_price_minor": 4500,
"extra_price": 0, "extra_price_minor": 0,
"line_total": 45.00, "line_total_minor": 4500,
"line_discount": 0, "line_discount_minor": 0,
"notes": null,
"selected_ingredients": [],
"added_ingredients": [],
"removed_ingredients": []
}
],

"created_at": "2026-06-28T18:42:11.000Z",
"updated_at": "2026-06-28T18:43:02.000Z"
}