Veri ve Entegrasyon
Şu an: fixture verisi
Ekranlarda görünen her rakam app/_data/panel.ts dosyasından gelir. Bu veriler
tasarım paketinden aktarıldı ve hiçbiri gerçek değil. Hiçbir ekran verisi
için fetch, server action ya da veritabanı çağrısı yoktur. Bunun üç istisnası
var ve hiçbiri ekran verisi taşımaz: oturum açma/kapama server action’ları
(app/auth/actions.ts), Supabase Auth çağrıları ve Lisans ekranının
POST /api/license/verify isteği.
Veriler ekran başına dağıtılmak yerine tek bir modülde toplandı. Böylece gerçek okumalara geçiş bu dosyaya ve ekranların import satırlarına dokunur, ekranların işaretlemesine dokunmaz.
Modülün içeriği
| Bölüm | Dışa aktarılanlar | Kullanan ekran |
|---|---|---|
| Menü | CATEGORIES, MENU_ITEMS, ALLERGENS, Category, MenuItem | Menü |
| Personel | STAFF, Staff, CURRENT_USER | Personel, Abonelik, kenar çubuğu |
| Hata kayıtları | ERRORS, ErrorRow | Hata Kayıtları, Panel |
| Denetim | AUDIT, AuditRow | Denetim Kaydı, Panel |
| Senkron | SYNC_RUNS, SYNC_STATE | Senkronizasyon, Panel, başlık |
| Şubeler | TENANTS | Başlık, kenar çubuğu |
| Cihazlar | DEVICE_REQUESTS, DEVICES, APP_VERSIONS, APP_NOTES, Device, DeviceConfig | Cihazlar, Uygulama Yönetimi, Abonelik |
| Stok | STOCK, MOVES, LAST_STOCK_COUNT, stockStatus() | Stok |
| e-Belge | DOCS, TAXPAYER | e-Belge · GİB |
| Abonelik | PLANS, INVOICES, SUBSCRIPTION, PLAN_LIMITS, cyclePrice() | Abonelik |
| Ayarlar | SETTINGS | Restoran Ayarları |
| Dashboard | KPI, HOURLY_REVENUE, CATEGORY_SHARE, PAYMENT_SPLIT, CLOSED_TICKETS_TODAY, OPEN_TABLES | Panel, e-Belge |
| Yardımcı | money(), BADGES | Her yerde |
Menü ürünleri üretilir. Ürünler, prototipin kullandığı formülle oluşturulur: fiyat kategori taban fiyatından türetilir, oto-ateşle Bar istasyonu ve Başlangıçlar kategorisinde açıktır, her 23. ürün satış dışıdır. On iki kategori tanımından 158 ürün bu yüzden çıkar. Yalnızca birkaç ürünün açıklama, içindekiler ve alerjen bilgisi dolu.
Türetilmiş sayaçlar
Kenar çubuğu rozetleri, stok durumu, stok değeri, zayi ve plan kullanımı gibi değerler saklanmaz, kaynak dizilerden hesaplanır. Böylece bir satırı düzenlemek, rozetin özetlediği tabloyla çelişmesine yol açamaz.
Rozet (BADGES) | Hesap |
|---|---|
itemTotal | MENU_ITEMS sayısı |
stockAlerts | Miktarı minimumun altındaki malzemeler (tükenenler dahil) |
deviceRequests | Bekleyen kayıt isteği sayısı |
pendingSync | SYNC_STATE.pending |
errors | ERRORS sayısı |
pendingDocs | Durumu Hata veya Kuyrukta olan belgeler |
planName | Mevcut planın adı |
Rozetler fixture’lardan hesaplanır, ekranların client state’inden değil. Menüde bir ürün silmek veya bir cihazı eşleştirmek kenar çubuğundaki sayıyı değiştirmez.
Stok rozeti tükenenleri de sayar; Stok ekranındaki “Kritik” hücresi ise yalnızca miktarı sıfırdan büyük olanları sayar ve tükenenleri notta ayrıca gösterir. Bu yüzden iki sayı farklı görünebilir.
Client state
Client ekranlar useState’i bu sabitlerle başlatır. Personel eklemek, cihaz
eşleştirmek ya da plan değiştirmek ekranda görünür, ama yalnızca o oturum için
geçerlidir ve sayfa yenilenince kaybolur. State ekranlar arasında da paylaşılmaz.
Şu an kaydedilecek bir yer olmadığı için bu bilinçli bir tercih.
Bilinen sınırlamalar
- Yeni kayıt kimlikleri çakışabilir. Menü kategorileri, menü ürünleri,
cihazlar ve personel için yeni id
önek + (dizi uzunluğu + 1)olarak üretilir. Önce bir kayıt silinip sonra yenisi eklenirse, üretilen id mevcut bir kayda denk gelebilir. Örneğin 12 kategoriden biri silinip yeni kategori eklenirse yeni idc12olur, ki bu zaten Kokteyller’in id’sidir. O durumda iki satır aynı React key’ini taşır ve düzenleme ikisine birden uygulanır. Kimlikler veritabanından gelmeye başladığında bu sorun ortadan kalkar; o zamana kadar düzeltilmedi. - Silme işlemleri onay istemez. Kategori silmek içindeki ürünleri de siler.
- Stok hareketi, e-belge oluşturma, yeniden gönderme, iptal ve ayar kaydetme yalnızca arayüzdür. Bkz. Ekranlar.
Gerçek veriye geçiş
Bir ekranı gerçek veriye bağlarken:
- Okumayı, veri gerektiren en yakın Server Component’e koyun. Client ekranlarda veriyi Server Component’te çekip prop olarak geçirin; bu, ekranı baştan client’a taşımaktan iyidir.
- İlgili fixture’ı
app/_data/panel.ts’ten kaldırın ve türetilmiş sayaçları (BADGESdahil) gerçek veriden hesaplayın. - Yazma işlemleri için server action kullanın ve “yalnızca arayüz” düğmelerini bağlayın. Başarısız olabilecek yıkıcı işlemler geldiğinde onay ve bildirim (toast) altyapısı gündeme gelmeli.
- Kullanılan her backend endpoint’i için aşağıdaki tabloya bir satır ekleyin.
Bu repo kendi endpoint’ini (route handler) açarsa onu
docs/api/altında belgeleyin. Bkz. Dokümantasyon düzeni. - Next.js 16’nın veri çekme ve önbellekleme davranışını
node_modules/next/dist/docs/altındaki rehberden doğrulayın. Eski sürümlerden hatırlanan davranışa güvenmeyin.
Supabase bulut şeması: migration/
migration/ klasörü, Claude Design’daki Adisyon Supabase Şema İlişkileri
diyagramından üretilmiş DDL’dir (kaynak paket:
supabase-table-relations-for-adisyon-admin/). 7 kulvarda 32 tablo, 36 ilişki,
23 enum. Uygulama sırası: migration/0*.sql, sonra migration/tables/01…32.
Hepsi idempotent.
Hiçbir Supabase projesine uygulanmadı ve panel buradan okumuyor. Ekranlar hâlâ fixture’larla çalışıyor. Ayrıntılı gerekçe, boşluklar ve doğrulama:
migration/README.md.
Bu, yerel Postgres şemasının kopyası değildir; onun üzerinde duran bir bulut şemasıdır. Tablolar iki biçimde gelir ve fark buradaki neredeyse her kararı belirler:
| ↕ senkron tabloları | yalnız-bulut tabloları | |
|---|---|---|
| Birincil anahtar | seq bigint | id uuid |
| Yerel iz | local_id uuid — FK değil | — |
| Kardeş bağları | seq üzerinden (order_seq, menu_item_seq, …) | id üzerinden |
| Denetim aktörü | created_by_seq → employees.seq | created_by → auth.users |
Senkron yönü: menü ve ayarlar buluttan yerele, sipariş, ödeme ve loglar
yerelden buluta. sync_runs ikisini de kaydeder. Panelin orders,
order_items ve payments üzerinde yazma yetkisi olmamasının sebebi bu — onlar
restoranda kapanır.
Kiracı izolasyonu her tabloda tenant_id ve tek bir politika kalıbıdır:
tenant_id = public.current_tenant_id(). O fonksiyon 02_functions.sql
içindedir ve SCRUM-141 kapanmadığı için tek değişim noktasıdır: önce
app_metadata.tenant_id JWT claim’ine bakar, yoksa tenant_users üzerinden
çözer. Karar hangi yöne düşerse düşsün otuz küsur politika değil, bir fonksiyon
değişir.
Denetim sütunları (SCRUM-193) her tabloda aynıdır: created_at,
created_by(_seq), updated_at, updated_by(_seq), data_origin.
updated_at trigger ile yazılır; updated_by yazılmaz — trigger aktörü
bilemez, onu yazan katman set etmelidir. Burada en kolay atlanan şey budur.
RLS’in koruyamadığı üç kolon kolon bazlı GRANT ile saklanır (RLS satır
düzeyindedir, kolon gizlemez): employees.pin_hash, licenses.license_key,
payment_methods.provider_token.
Enum değerleri diyagramda yok. Bir kısmı panelin fixture’larından ve yerel
şemadan türetildi, bir kısmı öneridir; hangisinin hangisi olduğu
migration/README.md’deki tabloda satır satır yazılı. Uygulamadan önce
önerilenlerin onaylanması gerekiyor.
Diyagramın kendi içinde çeliştiği üç yer ve şemadaki boşluklar (örneğin
order_items’ta iptal ayrıntısının olmaması — SCRUM-46’nın “760 TL’lik satırı
kim sildi” sorusu bu şemadan cevaplanamıyor) yine aynı dosyada listelendi.
Endpoint’ler
Panelin çağırdıkları
Panel hâlâ hiçbir Go backend endpoint’i çağırmıyor. Tek dış bağımlılık Supabase
Auth; @supabase/ssr üzerinden doğrudan çağrılır.
| Ekran | Endpoint / kaynak | Sahibi |
|---|---|---|
| Oturum aç, çıkış, proxy | Supabase Auth (signInWithPassword, signInWithOtp, exchangeCodeForSession, verifyOtp, getClaims, signOut) | Supabase projesi |
| Lisans | POST /api/license/verify — panelin kendi endpoint’i | Bu repo |
Panelin açtıkları
| Endpoint | Ne yapar | Belge |
|---|---|---|
GET / POST /api/license/verify | Yapıştırılan lisansı sunucuda Ed25519 ile doğrular, kalan günü hesaplar | Lisans doğrulama |
app/auth/confirm/route.ts de bir route handler’dır ama yalnızca Supabase’in
e-posta bağlantısının dönüş adresidir; dışarıdan çağrılacak bir API değildir.
Ekranları bekleten işler
Ekranların arayüz işleri SCRUM-19 (Admin Panel Foundation) epiği altındadır: kabuk ve navigasyon SCRUM-134, ekranlar SCRUM-186 … SCRUM-195. Gerçek veriye geçişi belirleyen işler:
| Ekran | İlgili iş |
|---|---|
| Kimlik doğrulama (tüm panel) | SCRUM-132 ile giriş/çıkış ve route koruması yapıldı; hesap ↔ çalışan/rol eşlemesi ve tenant claim’i (SCRUM-141) bekliyor |
| Menü | SCRUM-35 (menü CRUD), SCRUM-135 (Supabase → yerel senkron akışı), SCRUM-40 (yapay zekâ ile açıklama/alerjen) |
| Restoran Ayarları | SCRUM-36 (ekran), SCRUM-136 (restaurant_settings okuma/yazma server action’ı) |
| Personel & Roller | SCRUM-44 altında veri tarafı tamamlandı (SCRUM-176 employees, SCRUM-183 PIN ile giriş); panel bağlantısı yapılmadı |
| Hata Kayıtları | SCRUM-177 (error_logs’a doğru kayıt yazılması) |
| Denetim Kaydı | SCRUM-46 (sipariş işlemlerinin denetim kaydı) |
| Senkronizasyon | SCRUM-135, SCRUM-142 (senkron katmanında tenant_id) |
| Şube seçici | SCRUM-37 altında SCRUM-141 (session/JWT’de tenant claim), SCRUM-140 (tenant bazlı RLS) |
| e-Belge · GİB | GİB / entegratör entegrasyonu — henüz planlanmadı |
| Lisans | Ekran ve doğrulama yapıldı (SCRUM-234); lisansların kalıcı kaydı panel veritabanına bağlı, üretim açık anahtarı SCRUM-229 |
| Panel, Stok, Cihazlar, Uygulama Yönetimi, Abonelik | Veri kaynağı için henüz issue yok |
Backend’e ve yerel veritabanına ait değişiklikler kendi repolarında belgelenir
(smart-menu-adisyon-backend-dev, smart-menu-adisyon-localdb-dev). Bu sayfa
yalnızca panelin onlara olan bağımlılığını gösterir.