Çoğu işletme sahibi "bakiye düşmüyor" cümlesini duyduğunda aklına tek bir şey geliyor: veritabanındaki o küçük balance sütunu bozulmuş olmalı. Panele giriyor, bakiyeyi elle düzeltiyor, müşteriye özür mesajı atıyor ve günü kurtardığını düşünüyor. Oysa o sütun neredeyse hiçbir zaman suçlu değildir. Suçlu, siparişin doğduğu an ile bakiyenin yazıldığı an arasındaki o birkaç yüz milisaniyelik boşluğu kimsenin denetlemiyor olması.
Ben bu boşluğa "sessiz hata zinciri" diyorum. Çünkü ekranda hata çıkmaz, log'a kırmızı satır düşmez, müşteri kodu alır, sen de satış yaptığını sanırsın. Sadece ay sonunda kasa ile panel tutmaz. Bu yazıda o zinciri halka halka açacağım: siparişin hangi adımında bakiye yazılmalı, hangi adımda yazılırsa kaybolur, ve bir e-pin satış scripti bunu mimari olarak nasıl garanti altına alır. Anlatacaklarım teorik değil; bayilik modeliyle çalışan her e-pin yazılımı için birebir geçerli.
Gerçekten bakiye mi düşmüyor, yoksa hiç düşürülmesi istenmedi mi?
İlk soruyu yanlış sorarsan doğru cevaba asla ulaşamazsın. "Bakiye düşmüyor" dediğin durumların büyük kısmında script bakiyeyi düşürmeye hiç kalkışmamıştır. Çünkü siparişi oluşturan fonksiyon ile bakiyeyi azaltan fonksiyon aynı akışta değildir. Sipariş kaydı pending olarak açılır, stoktan kod ayrılır, müşteriye gösterilir; bakiye düşümü ise siparişin completed olmasına bağlı bir tetikleyiciye bırakılır. Sipariş o duruma hiç geçmezse bakiye de hiç düşmez.
Bunu test etmenin en hızlı yolu şudur: bir test bayisiyle küçük tutarlı sipariş ver, ardından sipariş tablosundaki durum alanına bak. Kod teslim edilmiş ama durum hâlâ beklemede görünüyorsa sorun bakiye tarafında değil, durum geçişlerinin hiç tamamlanmıyor olmasında. Bir dijital ürün satış scripti bu iki adımı asla ayrı bırakmamalı: teslimat gerçekleştiyse finansal kayıt da aynı işlemin parçası olmalıdır.
Transaction yoksa bakiye her zaman kaybolmaya adaydır
Bir siparişte en az dört tablo değişir: sipariş başlığı, sipariş satırı, stok/kod havuzu ve bakiye hareketi. Bu dördü tek bir veritabanı işlemi (transaction) içinde yazılmıyorsa, üçü başarılı olup dördüncüsü sessizce düşebilir. Klasik senaryo: kod havuzundan kod çekilir, müşteriye gösterilir, sonra bakiye satırı yazılırken bağlantı zaman aşımına düşer. Kod gitti, para gitmedi.
Doğru kurulum şudur: işlem başlatılır, bakiye kilitli okunur, yeterlilik kontrol edilir, kod ayrılır, bakiye hareketi yazılır, işlem onaylanır. Herhangi bir adım patlarsa tamamı geri alınır ve müşteri hata mesajı görür. Kötü haber şu: bunu sonradan bir epin yazılım kurulumuna eklemek, üstüne yama atmakla olmaz; sipariş servisinin baştan bu sırayla yazılmış olması gerekir. Pinova'nın sipariş katmanında bu sıra sabittir ve devre dışı bırakılamaz.
| Belirti | Gerçek kök neden | Nerede doğrular | Kalıcı çözüm |
|---|---|---|---|
| Kod teslim, bakiye aynı | Sipariş durumu tamamlanmaya hiç geçmiyor | Sipariş durum geçmişi | Teslimat ile finansal kaydı tek işleme al |
| Bakiye ekranda eski görünüyor | Önbellek geçersiz kılınmıyor | Aynı kaydı doğrudan veritabanından oku | Bakiye yazımında önbelleği zorla temizle |
| Kuruş farkları birikiyor | Tutar float saklanıyor | Hareket toplamı ile bakiye karşılaştırması | Ondalıklı sabit alan veya kuruş tamsayısı |
| Sadece yoğun saatte kayıp | Kilitsiz eşzamanlı okuma | Aynı saniyeye düşen iki sipariş | Satır kilidi ile bakiye okuma |
| Bayi bakiyesi düşmüyor, ana bakiye düşüyor | Hesap sahibi yanlış çözümleniyor | Hareket kaydındaki kullanıcı kimliği | Oturumdan değil siparişten hesap türet |
| İptalde bakiye geri gelmiyor | İade akışı ters hareket yazmıyor | Negatif hareket var mı | Her iptali ters kayıtla kapat |
Bakiyeyi hesaplamak mı, saklamak mı? İkisini karıştırmak kayıp üretir
İki meşru yaklaşım vardır. Birincisi bakiyeyi hareket tablosundan her seferinde toplayarak hesaplamak; ikincisi bir sütunda tutup her harekette güncellemek. Sorun, çoğu kurulumun ikisini birden yapıyor olması. Bir ekran toplamı gösterir, diğeri sütunu gösterir; ikisi ayrıştığında sen "bakiye düşmüyor" sanırsın, aslında iki farklı doğruya bakıyorsundur.
Sağlıklı mimari şudur: hareket tablosu tek gerçek kaynaktır, sütun yalnızca hızlı okuma için tutulan bir özettir ve her yazımda aynı işlem içinde tazelenir. Üstüne günlük bir mutabakat işi koyarsın: toplam hareket ile özet sütun arasındaki fark sıfır değilse seni uyarır. Bu tek kontrol, çoğu işletmenin ay sonu sürprizlerini tamamen bitirir.
Bakiye düşmeme vakalarının dağılımı
- Durum geçişi tamamlanmıyor 45%
- İşlem bütünlüğü yok 25%
- Önbellek / görüntüleme 20%
- Tutar tipi ve yuvarlama 10%
Önbellek seni neden bu kadar kolay kandırır?
Hız için bakiyeyi önbelleğe almak akıllıca. Ama önbelleği yalnızca süre bitiminde yenilemek felaket. Bayi sipariş verir, bakiye gerçekten düşer, ekran ise on dakika boyunca eski değeri gösterir. Bayi sana yazar: "bakiyem düşmedi". Sen veritabanına bakarsın, düşmüştür. İki taraf da haklıdır, sistem yanlıştır.
Kural nettir: bakiyeyi değiştiren her kod yolu, aynı anda o kullanıcının önbellek anahtarını geçersiz kılmak zorundadır. Ayrıca bakiye gösteren ekranlar tarayıcı tarafında da önbelleklenmemeli. Bunu e-pin satış yazılımı tarafında merkezi bir bakiye servisine bağlarsan, sonradan eklenen hiçbir modül bu kuralı atlayamaz.
Kuruşlar nereye gidiyor? Tutar tipi hatası
Fiyatları kayan noktalı sayı olarak saklayan bir sistemde 19,90 artı 0,10 her zaman tam 20,00 etmez. Tek satışta görünmez, binlerce satışta bakiye ile hareket toplamı arasında sürekli büyüyen bir fark üretir. Sen bunu "bakiye düşmüyor" diye okursun; gerçekte bakiye düşüyor ama yanlış ölçüyle düşüyor.
Çözüm sıkıcı ama kesin: tutarları ondalıklı sabit alanda ya da kuruş tamsayısı olarak tut, yuvarlamayı tek bir yardımcı fonksiyonda topla, döviz çevrimini sipariş anındaki kuru kaydederek dondur. Kur alanını siparişe yazmazsan, geçmiş siparişin bakiyesi bugünün kuruyla yeniden hesaplanır ve tablo bir daha asla tutmaz.
Şüpheli bayinin hareket toplamını al, bakiye sütunuyla karşılaştır. Fark varsa problem bakiye yazımında; fark yoksa problem ekranda veya önbellekte. Bu ayrım seni saatlerce yanlış yerde aramaktan kurtarır.
Bu sorunu bir daha yaşamamak için neyi şart koşmalısın?
Altyapı seçerken tek soru sor: "Bir siparişte para hareketi hangi anda ve hangi garantiyle yazılıyor?" Cevap net bir mimari anlatmıyorsa, o kurulumda bu sorun tekrar eder. Aşağıdaki listeyi kendi sistemine uygula; her satırın karşısına dürüstçe evet yazabiliyorsan bakiye kaybı senin için kapanmış bir dosyadır.
| # | Kontrol | Neden kritik | Durum |
|---|---|---|---|
| 1 | Teslimat ve bakiye aynı transaction içinde | Yarım kalan siparişte kayıp olmaz | Zorunlu |
| 2 | Bakiye satır kilidiyle okunuyor | Eşzamanlı siparişlerde tutarlılık | Zorunlu |
| 3 | Hareket tablosu tek gerçek kaynak | Her farkı izleyebilirsin | Zorunlu |
| 4 | Yazımda önbellek geçersiz kılınıyor | Sahte şikâyetler biter | Zorunlu |
| 5 | Tutarlar sabit ondalık veya kuruş | Yuvarlama birikmesi olmaz | Zorunlu |
| 6 | Sipariş anındaki kur kaydediliyor | Geçmiş kayıtlar sabitlenir | Önerilir |
| 7 | Günlük otomatik mutabakat uyarısı | Farkı sen değil sistem bulur | Önerilir |
| 8 | Manuel bakiye düzeltmesi de hareket yazıyor | Denetim izi kopmaz | Zorunlu |
Bakiye tutarlılığı sonradan eklenen bir özellik değildir
Pinova'nın sipariş ve cüzdan katmanı tek işlem bütünlüğü, satır kilidi ve zorunlu hareket kaydı üzerine kurulu. Kapsamı özellikler bölümünde, paketleri fiyat sayfasında görebilirsin.
Bakiyeyi elle düzeltmek kalıcı bir çözüm mü?
Hayır. Elle düzeltme yalnızca sonucu değiştirir, nedeni yerinde bırakır. Üstelik hareket kaydı yazılmadan yapılan düzeltme denetim izini koparır ve bir sonraki mutabakatta yeni bir fark üretir.
Bakiye tek sütunda mı tutulmalı yoksa hareketlerden mi hesaplanmalı?
Hareket tablosu gerçek kaynak olmalı, sütun ise aynı işlem içinde güncellenen bir hız özeti olarak kalmalı. Asıl kural, iki değerin asla ayrı yollardan yazılmaması.
Sorunu yalnızca yoğun saatlerde görüyorum, bu neyi gösterir?
Neredeyse kesin olarak eşzamanlılık problemidir. Bakiye kilitsiz okunuyor ve iki sipariş aynı anda aynı başlangıç değerini görüyor. Satır kilidi eklenmeden düzelmez.
Mevcut kurulumumda bu düzeltilebilir mi?
Genellikle evet, ancak sipariş servisi tek noktadan geçmiyorsa maliyet yükselir. Bakiyeyi değiştiren her kod yolunu tek bir cüzdan servisine indirmek ilk ve en değerli adımdır.
Bakiye tutarlılığı, bir dijital ürün satış yazılımı için süs değil temel taştır; çünkü güven kaybı iade edilemez. Kendi sipariş akışını yukarıdaki sekiz maddeye karşı ölç, sonra aynı akışın doğru kurulmuş halini canlı demo üzerinde dene ve iki kurulum arasındaki farkı kendi gözünle gör.

