İçindekiler
Fiyatlandırma
Bir satırın fiyatı, sırayla değerlendirilen fiyat listelerinden ilk eşleşenden gelir. Sonuç yalnızca sayı değildir: hangi listelerin bakıldığını, her birinin neden atlandığını ve hangi kırılımın tuttuğunu gösteren sıralı bir iz de döner.
Dağıtıcının arka ofisinde en çok zaman alan soru şudur: “bu dükkân bu koliye neden ₺469,20 ödüyor?” Cevabı bulmak, kimin hangi listeye bağlı olduğunu, hangi kampanyanın o gün yürürlükte olduğunu ve hangi miktar kırılımının tuttuğunu elle takip etmeyi gerektirir. Rutix bu izi hesaplamanın kendisinden üretir — yani açıklama, temsilciye gösterilen fiyattan sapmaz, çünkü ikisi aynı kod yolundan çıkar.
Fiyat listesi #
Bir fiyat listesi başlığı şunları taşır:
| Alan | Anlamı |
|---|---|
| Ad ve kod | Kod kiracı içinde tekildir; ikinci bir liste aynı kodu alamaz. |
| Para birimi | Varsayılan TRY. |
| Geçerlilik | Başlangıç tarihi ve isteğe bağlı bitiş tarihi. Bitiş boşsa liste açık uçludur. Bitiş, başlangıçtan önce olamaz. |
| Kanal | Doluysa liste yalnızca o kanaldaki müşteriler için aday olur. |
| Organizasyon birimi | Doluysa liste o distribütöre/şubeye bağlanır. |
| Öncelik | Tam sayı. Aynı katmandaki listeler arasında büyük olan kazanır. |
| Varsayılan mı | Kiracı başına tek bir varsayılan liste olabilir. Bir listeyi varsayılan yapmak diğerlerinin varsayılanlığını kaldırır. |
| Durum | Taslak, aktif ya da arşivlenmiş. Yalnızca aktif listeler aday olur. |
Adaylar nasıl toplanır #
Bir müşteri–ürün–birim–tarih sorgusu için önce aday listeler toplanır. Bir liste aday olabilmek için aktif olmalı, sorgu tarihinde geçerli olmalı ve şu dördünden en az birini sağlamalıdır: müşterinin kendisine atanmış liste olmak, müşterinin kanalıyla eşleşmek, müşterinin organizasyon birimiyle eşleşmek ya da varsayılan liste olmak.
Her aday, hangi sebeple aday olduğuna göre bir katmana yerleşir. Sıra bu dört maddeyle aynıdır ve ilk eşleşen kazanır — bir liste hem müşteriye atalı hem varsayılansa, müşteri katmanında sayılır.
Sıralama ve eşitlik bozma #
Adaylar şu sırayla dizilir:
- Katman. Müşteriye özel liste → kanal listesi → distribütör listesi → genel liste.
- Öncelik. Aynı katmanda büyük öncelik önce gelir.
- Ad. Kalan eşitlik ada göre bozulur, böylece sonuç satır sırasına bağlı kalmaz ve iki çalıştırma aynı cevabı verir.
Katman öncelikten önce geldiği için, müşteriye atanmış bir liste, önceliği daha yüksek bir varsayılan listeyi yener. Bu bilinçli: bir müşteriye özel liste atamak, o müşteriyi genel tarifeden çıkarmak demektir; genel listenin önceliğini yükseltmek bunu geri almamalıdır.
Motor sırayla ne yapar #
- 1
Hiç aday yoksa
İz tek bir adım taşır:price.no_candidates. Bu müşteriye hiçbir fiyat listesi uygulanmıyor demektir. - 2
Aday sırayla denenir
Sorgu tarihinde geçerli olmayan bir adayprice.list_not_effectiveile atlanır ve iz o tarihi de yazar. - 3
Miktar kırılımı aranır
Listede o ürün ve o birim için satır varsa, istenen miktarın karşıladığı en yüksek kırılım seçilir. Kırılımlı eşleşmeprice.matched_at_break, kırılımsız eşleşmeprice.matchedkoduyla yazılır ve motor orada durur. - 4
Yoksa taban birimden türetilir
Liste istenen birimi fiyatlamıyorsa ve ürünün o birim için birden büyük bir katsayısı varsa, fiyat taban birimden türetilir:price.derived_from_base_unit. Türetme her aday liste için, bir sonrakine geçmeden önce denenir. - 5
Bu liste bu ürünü taşımıyorsa
price.no_entryyazılır ve sıradaki adaya geçilir. Bütün adaylar tükenirse izprice.exhaustedile kapanır.
Miktar kırılımları #
Bir fiyat satırı ürün, birim, fiyat ve en az miktar taşır. En az miktarı sıfır olan satır taban fiyattır. Kendi tarih penceresi de olabilir, yani liste başlığından bağımsız olarak bir kırılım belli bir tarih aralığında çalıştırılabilir.
Seçim kuralı: istenen miktarın karşıladığı kırılımlar arasında en az miktarı en yüksek olan kazanır. En az miktarları eşitse düşük fiyat kazanır — veri girişinden kalan bir çift kayıt asla müşteriye pahalıya patlamaz. Hiçbir kırılım karşılanmıyorsa taban fiyat kullanılır.
Yazma tarafında aynı liste, ürün, birim ve en az miktar için ikinci bir satır reddedilir. Aksi hâlde “iki fiyattan ucuzu tesadüfen kazanır”, ve hangisinin kazandığı satır sırasına bağlı olur — bu ürünün karşı durduğu belirsizliğin ta kendisi.
Birimler: ADET, KOLİ, PALET #
Bir ürün adetle sayılır, koliyle sipariş edilir ve paletle taşınır. Aradaki katsayı her fiyatın, her stok hareketinin ve her promosyon eşiğinin üzerinden hesaplandığı sayıdır. On iki kat yanlış olması bir yuvarlama hatası değildir ve faturaya kadar görünmez — bu yüzden ürün formu birim tablosunun etrafına kurulmuştur.
Bir liste yalnızca adet fiyatını taşıyorsa koli fiyatı taban fiyat × katsayı ile türetilir. Türetmeden önce kırılım araması taban birime çevrilmiş miktarla yapılır, yani adet bazlı kırılımlar da doğru değerlendirilir. Türetme tek yönlüdür: koli fiyatından bölerek adet fiyatı üretilmez.
“Bu fiyat neden bu” #
GET /pricing/explain çözülen fiyatı ve izin tamamını döner. Panelde bu iz numaralı bir liste olarak gösterilir; aynı iz, satış anında sipariş satırına da yazılır.
İzin her adımı bir kod, o koda ait değerler ve hesaplandığı andaki metin taşır. Cümle istemcide, okuyanın dilinde kurulur. Bunun sebebi pratiktir ve bu üründe birden fazla yerde tekrarlanmıştır: bugün donmuş bir cümle yarın başka bir dilde gösterilemez, ve bir fiyat itirazı aylar sonra tam olarak bu kaydın üzerinden çözülür.
| Kod | Ne demek | Taşıdığı değerler |
|---|---|---|
| price.no_candidates | Bu müşteriye hiçbir fiyat listesi uygulanmıyor. | — |
| price.list_not_effective | Liste aday ama sorgu tarihinde geçerli değil. | liste adı, tarih |
| price.matched | Bu listede bu ürün ve birim için fiyat bulundu. | liste adı, birim, fiyat, para birimi |
| price.matched_at_break | Miktar kırılımı tuttu. | liste adı, birim, fiyat, para birimi, en az miktar |
| price.derived_from_base_unit | Bu birimin fiyatı yok; taban birimden türetildi. | liste adı, birim, taban birim, taban fiyat, katsayı, sonuç |
| price.no_entry | Liste geçerli ama bu ürün/birim için satırı yok. | liste adı, birim |
| price.exhausted | Bütün adaylar bakıldı, hiçbiri bu ürünü taşımıyor. | — |
GET /pricing/explain?customerId=<müşteri>&productId=<ürün>&unit=KOLI&quantity=10
{
"unitPrice": 469.20,
"currency": "TRY",
"priceListName": "Marmaris HORECA 2026",
"source": "channel",
"derivedFromBaseUnit": false,
"trace": [
{ "order": 1, "code": "price.list_not_effective", "matched": false,
"values": { "listName": "Yaz Tarifesi", "onDate": "2026-08-20" } },
{ "order": 2, "code": "price.matched_at_break", "matched": true,
"values": { "listName": "Marmaris HORECA 2026", "unit": "KOLI",
"price": 469.20, "currency": "TRY", "minQuantity": 10 } }
]
}Yazarken reddedilenler #
Fiyat listesi yazma uçları, temiz kaydedilip sonra hiçbir şey yapmayan veriyi reddeder — bulunması bir gün süren hata türü budur:
- Başka bir listenin kullandığı kod.
- Başlangıcından önce biten geçerlilik penceresi.
- Negatif fiyat.
- Ürünün satılmadığı bir birim için fiyat — hiç eşleşmez ve belirtisi, birinin fiyatladığından emin olduğu bir satırda “fiyat bulunamadı” olur.
- Aynı miktar kırılımına ikinci bir fiyat.
- KOLİ’yi iki kez listeleyen bir ürün, ya da sıfır birim katsayısı.