Senaryo
Anadolu Market mobil uygulamasına kalıcı sepet özelliği eklenecek. Kullanıcı sepete ürün ekler, adet değiştirir, siparişe çevirir. API ekibi senden şemayı ve uç noktaların çalıştıracağı sorguları istiyor.
Gereksinimler
- Bir müşterinin tek açık sepeti olur; sepette aynı ürün bir kez bulunur (adet artar).
- Adet 1–20 arasında olmalı.
- Ürün listesi sayfalaması derin sayfalarda da hızlı olmalı.
- Siparişe çevirme tek işlemde yapılmalı; yarım kalırsa hiçbir şey değişmemeli.
Adımlar ve beklenen çıktı
| Adım | Ne yapacaksın? | Ders |
|---|---|---|
| 1. Şema | Sepet ve sepet satırı tabloları; tekillik, yabancı anahtar ve CHECK kısıtları | Kısıtlar ayrıntılı |
| 2. Sepete ekle | Ürün sepette varsa adedi artıran, yoksa ekleyen tek ifade (upsert) | UPSERT ve MERGE |
| 3. Ürün listesi | OFFSET yerine son görülen anahtardan devam eden sayfalama | Uygulamalarda sayfalama |
| 4. Sepet özeti | Satır tutarları ve genel toplam | JOIN ile özetleme |
| 5–6. Tasarım soruları | İşlem bütünlüğü ve tekrar eden istekler | Transaction, Uygulama veritabanı desenleri |
Tasarım notları
- “Bir müşterinin tek açık sepeti” kuralı
UNIQUE (customer_id)ile veritabanında korunur. - “Aynı ürün sepette bir kez” kuralı bileşik birincil anahtarla sağlanır:
PRIMARY KEY (cart_id, product_id). Bu aynı zamanda upsert'in çakışma hedefidir. - Adet sınırı
CHECK (quantity BETWEEN 1 AND 20)ile yazılır; uygulama bir hata yapsa bile geçersiz adet kaydedilemez.
Siparişe çevirme işleminin iskeleti
BEGIN;
-- 1) Sipariş başlığı
INSERT INTO orders (order_id, customer_id, order_date, status, channel)
VALUES (:yeni_id, :musteri, :bugun, 'shipped', 'mobile');
-- 2) Sepet satırlarını sipariş satırına kopyala (fiyat o anki fiyattır)
INSERT INTO order_items (order_id, product_id, quantity, unit_price, discount)
SELECT :yeni_id, ci.product_id, ci.quantity, p.price, 0
FROM cart_item ci JOIN products p ON p.product_id = ci.product_id
WHERE ci.cart_id = :sepet;
-- 3) Stok düş; stok yetmezse işlemi geri al
UPDATE products SET stock = stock - (SELECT ci.quantity FROM cart_item ci
WHERE ci.cart_id = :sepet AND ci.product_id = products.product_id)
WHERE product_id IN (SELECT product_id FROM cart_item WHERE cart_id = :sepet);
-- 4) Sepeti boşalt
DELETE FROM cart_item WHERE cart_id = :sepet;
COMMIT;
Adımlardan biri hata verirse uygulama ROLLBACK çalıştırır ve hiçbir tablo değişmez. Stok kontrolü için 3. adımdan önce yetersiz stoklu satır olup olmadığı sorgulanabilir ya da CHECK (stock >= 0) kısıtı ihlali hatası yakalanabilir.
Karar
Uç noktaları yayına almadan önce sepet okuma ve ürün listesi sorgularının planını al, indeks kararını ve yazma bedelini kısa bir notla ekibe yaz. Sorgu ne sıklıkla çalışıyor, tablo ne sıklıkla yazılıyor? Bu proje sonunda şema, sorgular ve indeks birlikte teslim edilir.