Blog / Ürün

B2B e-ticarette cari hesap: vadeli ödeme ve toplu sipariş

Kurumsal alıcı bireysel müşteri gibi davranmaz: MatbaaStore B2B modülünün tasarım kararları.

Her ayın ilk haftası, bir reklam ajansının ofis sorumlusu MatbaaStore'a giriyor ve neredeyse aynı işi tekrar sipariş ediyor: kendi ajansı için 5.000 kartvizit, üç müşterisi için üç ayrı katalog, bir de fuara yetişmesi gereken 2.000 broşür. Toplam beş haneli bir tutar. Ama o sorumlu ne kredi kartı çıkarıyor, ne de her siparişte "ödeme onaylanıyor" ekranını görmek istiyor. Beklentisi tek cümleyle özetlenebilir: siparişi ver, iş üretime düşsün, ay sonunda tek faturayı gör, vadesinde öde. Bu bir cümle, B2C e-ticaretin üzerine kurulu bütün varsayımları yerinden oynatır.

Yıllar bize şunu öğretti: B2B e-ticaret, "daha çok kullanıcılı B2C" değildir. Vitrini aynı olabilir, ürün kataloğu aynı olabilir, hatta fiyatlandırma motoru bile aynıdır — ama alıcının kim olduğu, parayı ne zaman ödediği, kararı nasıl verdiği ve platformdan ne beklediği tamamen başkadır. B2C'de tek bir kişi hem karar verir hem öder hem teslim alır. B2B'de bu üç rol çoğu zaman üç ayrı insandır; hatta ödeme, siparişten haftalar sonra, bambaşka bir departmandan gelir. MatbaaStore'un kurumsal modülünü kurarken en pahalı derslerimizi tam da bu ayrımı geç fark ettiğimiz yerlerde aldık.

Bu yazıda MatbaaStore'un B2B tarafını nasıl tasarladığımızı anlatacağız: B2C ile B2B alıcı davranışının nerede ayrıldığını, cari hesap ve bakiye modelini neden bir "mutable alan" değil bir defter olarak kurduğumuzu, özel fiyat listeleriyle müşteri segmentasyonunu fiyat motoruna nasıl bağladığımızı, vadeli ödemenin getirdiği kredi riskini limit yönetimiyle nasıl sınırladığımızı, tekrar sipariş akışının bir ajans için neden asıl değer olduğunu ve bütün bunların faturalama ile muhasebeye nasıl oturduğunu. Somut senaryolar matbaa sektöründen; ama çıkardığımız dersler her B2B platformu için geçerli.

B2C ile B2B: aynı vitrin, bambaşka alıcı

Bir B2C müşterisi kartvizit sipariş ederken duygusaldır ve tekildir. Fiyatı görür, beğenirse öder, bir daha da belki altı ay uğramaz. Kararı anlıktır, sadakati zayıftır, ödemesi peşindir. Platformu buna göre kurarsanız yanılmazsınız: sepet, kredi kartı, teşekkürler ekranı. B2B alıcısı ise bunların hiçbirine benzemez. O bir kere gelmez, düzenli gelir; tek başına karar vermez, onay zinciri vardır; peşin ödemez, vadeyle çalışır; ve en önemlisi, fiyatı "liste fiyatı" olarak değil "bana özel fiyat" olarak görmek ister.

Bu farkları soyut bırakmamak için, matbaa özelinde gözlemlediğimiz somut ayrımları sıraladık:

  • Sıklık ve tekrar: B2C müşterisi yılda bir-iki sipariş verir; bir ajans ayda onlarca. B2B'de asıl değer ilk siparişte değil, ikinci ve sonraki siparişlerin ne kadar sürtünmesiz olduğundadır.
  • Karar ile ödemenin ayrışması: Siparişi ajansın tasarımcısı verir, onayı hesap yöneticisi geçer, ödemeyi muhasebe yapar. Tek bir "kullanıcı" varsayımı bu üç rolü tek hesaba sıkıştırır ve süreç tıkanır.
  • Ödeme zamanı: B2C'de para siparişten önce gelir, B2B'de sonra. Bu tek başına, "önce tahsilat sonra üretim" akışını çöpe atar; üretim, tahsilatı beklemeden başlamak zorundadır.
  • Fiyat beklentisi: Kurumsal alıcı liste fiyatını "başlangıç noktası" sayar. Ona pazarlıkla ya da sözleşmeyle kazandığı özel fiyatı göstermezseniz, telefonu açıp o eski usul teklif trafiğini geri getirir.
  • Hata toleransı: B2C'de yanlış giden bir kartvizit üzülür, iade eder. B2B'de aynı hata, ajansın kendi müşterisine karşı mahcup olması demektir; güven bir kez kırılır, hesap kapanır.

Bu listeye bakınca çıkan sonuç şu: B2B modülü, katalogun üstüne yapıştırılan bir "kurumsal" rozeti değil, alışverişin altındaki para ve kimlik modelinin yeniden düşünülmesidir. MatbaaStore'da B2C akışı ayakta dururken kurumsal akışı yanına ekledik; ama ikisinin ortasındaki fiyat motorunu ve sipariş hattını ortak tuttuk. Ortak kalması gereken çekirdek ile ayrışması gereken davranışı doğru yerden bölmek, projenin en kritik mimari kararıydı.

Bir başka gözlem de kimlik ve yetki tarafında oldu. B2C'de hesap tektir; kim girerse o alışveriş yapar. Kurumsal hesapta ise tek bir cari altında birden fazla kullanıcı bulunur: sipariş verebilen tasarımcı, onay verebilen yönetici, sadece faturaları görebilen muhasebeci. Bu rolleri en baştan ayrı yetkilerle kurmadığımız takdirde, ya herkes her şeyi yapar ya da tek bir parola bütün ekipte dolaşır. MatbaaStore'da her kurumsal cariye bağlı kullanıcıları rol bazında ayırdık; kimin sipariş açabileceği, kimin vadeli ödemeyi onaylayabileceği ve kimin yalnızca rapor görebileceği hesap düzeyinde tanımlanıyor. Kurumsal alıcı, platformu kendi iç hiyerarşisine oturtabildiği ölçüde ciddiye alır.

Cari hesap: siparişi ödemeden ayırmak

B2B'nin kalbi cari hesaptır. Cari hesap, bir kurumsal müşterinin bize olan borç-alacak ilişkisini zaman içinde tutan defterdir. B2C'de böyle bir şeye gerek yoktur çünkü her sipariş kendi içinde kapanır: ödedi, bitti. B2B'de ise sipariş üretime düşer, mal teslim edilir, fatura kesilir ve ödeme günler-haftalar sonra gelir. Bu sürede müşterinin bize bir borcu birikir. Cari hesap işte bu birikimi takip eder.

Erken dönemde yaptığımız ve sonradan söktüğümüz bir hata şuydu: bakiyeyi cari kaydın üzerinde tek bir sayı alanı olarak tutmak. Her sipariş geldiğinde bu alanı artırıyor, her tahsilatta azaltıyorduk. Kâğıt üzerinde temiz görünür; pratikte felakettir. Çünkü bir bakiye, kendisini oluşturan hareketlerden koparıldığı an denetlenemez hale gelir. "Bu 42.000 TL borç nereden çıktı?" sorusuna cevap veremezsiniz. Bir hata, bir çift kayıt, bir iptal — hepsi o tek sayıya sessizce sızar ve ay sonunda müşteriyle telefonda tartışırsınız.

Bakiye saklanacak bir değer değil, hesaplanacak bir sonuçtur. Muhasebenin beş yüz yıllık dersi budur: gerçeğin kaynağı hareketlerdir, bakiye onların toplamıdır. Bakiyeyi kaydederseniz, er ya da geç hareketlerle çelişir.

Bu yüzden modeli tersine çevirdik. Cari hesap, değiştirilemez hareket kayıtlarından oluşan bir defter oldu; bakiye ise bu hareketlerin anlık toplamı. Sipariş bir borç hareketi yazar, tahsilat bir alacak hareketi, iade bir düzeltme hareketi. Hiçbir kayıt silinmez, hiçbir kayıt değiştirilmez; yanlış varsa ters kayıtla düzeltilir. Böylece her bakiye, kendisini oluşturan satırlara kadar geri izlenebilir.

type Hareket struct {
    Tarih  time.Time
    Tur    HareketTuru // Siparis, Tahsilat, Iade, Duzeltme
    Tutar  Kurus       // borç (+), alacak (−) — kuruş cinsinden tam sayı
    Ref    string      // sipariş no ya da dekont no
}

func (c *Cari) Bakiye() Kurus {
    var b Kurus
    for _, h := range c.Hareketler {
        b += h.Tutar
    }
    return b // pozitif: müşteri bize borçlu
}

Bir ayrıntı ama can alıcı: parayı hiçbir zaman float64 olarak tutmadık. Fiyat motorunda ondalık hesap yaparız, ama cari deftere yazarken kuruşa yuvarlayıp tam sayı olarak sakladık. Kayan noktalı para, bir gün mutlaka bir kuruşluk yuvarlama farkı üretir ve o fark, mutabakat toplantısında saatlerinizi yer. Muhasebeyle konuşan her sistemde parayı tam sayı kuruş olarak tutmak pazarlık konusu değildir. Cari hesabı defter olarak kurduğumuz gün, "bu borç nereden geldi" sorusu bir tartışma olmaktan çıkıp bir sorgu haline geldi.

Özel fiyat listeleri ve müşteri segmentasyonu

Kurumsal alıcı liste fiyatını görmek istemez; kendi fiyatını görmek ister. Bir matbaada bu fiyatın kaynağı ciddidir: bir ajans yıllık cilt taahhüdü verdiği için kuşe kağıtta yüzde on iki iskonto almıştır, bir kurumsal müşteri sözleşmeyle belirli ürünlerde sabit fiyat kilitlemiştir, bir bayi ise ürün grubu bazında kademeli iskonto ile çalışır. Bunların hepsini "kupon kodu" mantığıyla çözmeye kalkarsanız, üç ay sonra kimin hangi fiyatı neden gördüğünü kimse açıklayamaz.

Biz özel fiyatı, fiyatlandırma motorunun en sonundaki marj katmanına bağlı bir kural olarak modelledik. Anlık fiyatlandırma motorunu yazarken maliyeti katmanlara ayırmış ve kâr marjını bilerek en sona bırakmıştık; işte o karar burada karşılığını verdi. Ham maliyet herkes için aynı hesaplanır — kağıt, baskı, son işlem, fire değişmez. Değişen tek şey en son uygulanan marj ve iskonto katmanıdır. Müşteriye özel fiyat, çekirdeği kirletmeden bu katmana bir kural olarak girer.

Fiyatın kime uygulanacağını ise segmentasyon belirler. Her cari hesabı bir ya da birden çok segmente bağladık: bireysel, ajans, kurumsal, bayi. Fiyat listeleri segmente ya da doğrudan cari hesaba bağlanabiliyor. Bir sipariş fiyatlanırken motor şu sırayı izliyor: önce cari hesaba özel sözleşme fiyatı var mı, yoksa segment fiyat listesi, o da yoksa genel liste fiyatı. İlk eşleşen kazanır. Bu basit öncelik zinciri, "en özelden en genele" ilkesiyle, yüzlerce farklı fiyat ilişkisini tek bir okunur kuralda topladı.

Bir anti-pattern uyarısı: özel fiyatı ürünün üzerine yazmayın. Yani "bu müşteri için bu ürünün fiyatı şudur" diye statik bir tabloya kaydetmeyin. Çünkü matbaada fiyat üründen değil, konfigürasyondan doğar; aynı kartvizit, gramaj ve selefon değişince başka üründür. Özel fiyatı bir çarpan ya da iskonto oranı olarak modellediğinizde, müşteri hangi varyantı seçerse seçsin indirimi hak ettiği yerde bulur. Sabit fiyat kaydı ise sadece o an tanımladığınız varyantta çalışır, geri kalan her kombinasyonda müşteri yine liste fiyatını görür ve size kızarak telefonu açar.

Vadeli ödeme, kredi limiti ve risk yönetimi

Vadeli ödemeyi açtığınız an, farkında olmadan bankacılık yapmaya başlarsınız. Müşteriye "önce al, sonra öde" dediğinizde ona kredi vermiş olursunuz; ve her kredinin bir riski vardır. Bir ajans batabilir, bir kurumsal müşteri ödemeyi geciktirebilir, bir bayi kapasitesinin çok üstünde sipariş verip ödeyememe noktasına gelebilir. B2B modülünü kurarken en çok kafa yorduğumuz alan, satışı kolaylaştırmakla tahsilat riskini sınırlamak arasındaki dengeydi.

Çözümün merkezinde kredi limiti var. Her cari hesabın bir kredi limiti oluyor; bu limit, o müşterinin bize aynı anda ne kadar borçlu kalabileceğinin tavanı. Ama burada ilk yaptığımız hata şuydu: limiti sadece mevcut bakiyeyle karşılaştırmak. Oysa bakiye, henüz faturalanmamış açık siparişleri görmez. Müşteri limitinin dibindeyken arka arkaya beş büyük sipariş verirse, her biri "bakiye henüz düşük" diye geçer ve limit kâğıt üzerinde aşılmadan gerçek risk ikiye üçe katlanır.

Bu yüzden kullanılabilir limiti üç kalemle hesaplıyoruz: mevcut cari bakiye, artı üretimdeki ama henüz faturalanmamış açık siparişlerin toplamı, artı yeni sipariş tutarı. Bu üçünün toplamı kredi limitini aşıyorsa sipariş vadeye kapanmaz; müşteri ya limitini artırmak için görüşür ya da o siparişi peşin öder.

func (c *Cari) VadeUygun(yeni Kurus) error {
    kullanilan := c.Bakiye() + c.AcikSiparisToplami()
    if kullanilan+yeni > c.KrediLimiti {
        return fmt.Errorf("limit aşıldı: kullanılabilir %d, gereken %d",
            c.KrediLimiti-kullanilan, yeni)
    }
    if c.VadesiGecmisVar() {
        return ErrVadeGecikmesi // eski borç varken yeni vade açma
    }
    return nil
}

İkinci kural, koddaki o küçük kontrolde saklı: vadesi geçmiş borcu olan bir müşteriye yeni vade açmayız. Bu bir teknik detay değil, bir tahsilat politikasıdır. Müşteri bir önceki faturasını ödemeden yeni siparişi vadeye yazarsanız, riski büyütmekten başka bir şey yapmazsınız. Sistem bu durumda siparişi engellemez — sadece vadeli ödeme seçeneğini kapatır; müşteri isterse peşin devam eder. Satışı öldürmeden riski durdurmak, bu ince ayarla mümkün oldu.

Bir de görünürlük meselesi var. Kredi limitini bir "hayır" mekanizması olarak saklamak yerine, kurumsal panelde açıkça gösterdik: limit ne kadar, ne kadarı kullanılmış, ne kadarı boşta. Ajans sorumlusu ay sonuna doğru limitinin dolduğunu önceden gördüğünde telefon açıp konuşuyor; sipariş anında sürpriz bir retle karşılaşmıyor. Riski yönetmenin en ucuz yolu, onu müşteriden gizlemek değil, müşteriyle paylaşmaktır.

Tekrar sipariş: ajansın asıl zaman kazandığı yer

Şimdi en baştaki ajans sorumlusuna geri dönelim. Onun için MatbaaStore'un değeri anlık fiyatlandırmada da değil, cari hesapta da değil — o aynı işi her ay yeniden kurmak zorunda kalmamasında. Bir B2B alıcısının hayatı tekrardan ibarettir: aynı kartvizit, aynı katalog, sadece adı ve adedi değişen aynı broşür. B2C dünyasında her sipariş sıfırdan kurulur; B2B'de bu bir işkencedir.

Tekrar sipariş akışını bu yüzden birinci sınıf bir özellik olarak kurduk, "sipariş geçmişi" ekranının içine gömülü bir buton olarak değil. Geçmiş her sipariş, tüm konfigürasyonuyla — ebat, gramaj, kağıt, selefon, adet, hatta yüklenen tasarım dosyası — bir şablona dönüşebiliyor. Ajans sorumlusu "yeniden sipariş ver" dediğinde, önünde doldurulacak boş bir form değil, geçen ayki siparişin birebir aynısı açılıyor; o sadece adedi güncelliyor ya da müşteri adını değiştiriyor.

Burada dikkat ettiğimiz bir incelik şu oldu: tekrar siparişte fiyatı dondurmadık. Yani "geçen ay ne ödediyse yine onu öder" demedik. Çünkü kağıt fiyatı değişmiş olabilir, müşterinin iskontosu güncellenmiş olabilir, kampanya bitmiş olabilir. Tekrar sipariş konfigürasyonu kopyalar ama fiyatı o anki motordan yeniden hesaplatır. Böylece ajans, doğru ve güncel fiyatı görür; biz de eski bir fiyatı taahhüt etmiş duruma düşmeyiz. Konfigürasyonu tekrarlamak kolaylık, fiyatı tekrarlamak ise gizli bir borçtur.

Ajanslara özel eklediğimiz bir katman da çok sipariş yönetimi oldu. Bir ajans aynı anda üç müşterisi için üç farklı iş verir; bunları tek sepette toplayıp tek onaya, tek sevkiyata ve tek faturaya bağlayabiliyor. Ama her işin kendi teslimat adresi ve kendi referans etiketi kalıyor — çünkü ajans o kataloğun A müşterisine, bu broşürün B müşterisine gittiğini kendi kayıtlarında ayırmak zorunda. Toplu siparişi tek para akışında birleştirip teslimatta ayrıştırmak, ajansın kendi iç muhasebesine birebir oturdu.

Rakamla konuşalım, çünkü bu özelliğin değeri ölçülebilir. Telefonla teklif devrinde bir ajans, tek bir tekrar iş için ortalama bir-iki gün bekliyordu: teklif iste, fiyatı bekle, onayla, dosyayı e-postayla gönder, üretim onayını bekle. Aynı iş, kayıtlı bir şablon ve açık bir cari hesapla artık dakikalar sürüyor; sorumlu şablonu açıyor, adedi güncelliyor, sipariş anında üretime düşüyor. Ayda onlarca sipariş veren bir ajans için bu, ayda kazanılan günler demek. B2B'de sadakati yaratan indirim değil, işte bu sürtünmesizliktir; bir kez bu akışa alışan ajans, birkaç kuruş ucuz diye başka bir yerde yeniden sıfırdan form doldurmaya kolay kolay geri dönmez.

Faturalama ve muhasebe entegrasyonu

Bütün bu cari hesap, vade ve tekrar sipariş yapısı, bir yerde gerçek dünyanın muhasebesine bağlanmak zorunda. Türkiye'de bu, e-fatura ve e-arşiv demek. B2B modülünü tamamlayan son parça, sipariş akışının faturalamaya sürtünmesiz bağlanmasıydı — çünkü fatura kesilmeyen bir sipariş, cari hesapta asılı kalır ve tahsilat başlamaz.

Önemli bir tasarım kararı: faturayı sipariş anında değil, sevkiyat anında kesiyoruz. Matbaada üretim gün alır ve bazen iş üretim sırasında iptal olur ya da düzeltilir. Siparişte fatura kesseydiniz, her iptalde bir iade faturasıyla uğraşırdınız. Mal sevk edilince fatura kesmek, hem yasal olarak doğru hem de cari hesabı gereksiz düzeltme hareketlerinden temiz tutuyor. Sevkiyat tetikleniyor, e-fatura otomatik oluşuyor, cari hesaba borç hareketi düşüyor ve tahsilat saati başlıyor.

Faturalamayı cari hesaba bağlarken kurduğumuz köprü, "her fatura bir borç hareketi, her tahsilat bir alacak hareketi" ilkesiydi. Muhasebe programına aktarım da bu hareketler üzerinden yürüyor; sistem bakiyeyi değil, hareketleri gönderiyor. Böylece bizim defterimizle müşterinin defteri satır satır mutabık kalıyor. Ay sonu mutabakatı, eskiden telefonla saatler süren bir çekişmeyken, artık iki defterin aynı hareket listesini karşılaştırmasından ibaret.

Bir de toplu faturalama ihtiyacı çıktı. Kimi kurumsal müşteri her sevkiyatta ayrı fatura istemez; ay boyunca biriken sevkiyatları tek bir dönem faturasında toplamak ister. Bunu da hareket defteri sayesinde kolay çözdük: sevkiyatlar cari hesaba borç hareketi olarak düşmeye devam eder, ama fatura kesimi dönem sonuna ertelenir ve o döneme ait hareketler tek faturada toplanır. Defteri hareket temelli kurduğumuz için, faturalama ritmini değiştirmek modeli hiç bozmadı — sadece hangi hareketlerin ne zaman faturalanacağını değiştiren bir gruplama kuralı oldu.

Sonuç

MatbaaStore'un B2B modülünü kurarken öğrendiğimiz asıl ders teknik değil, kavramsaldı: B2B e-ticaret, satışın üstüne eklenen bir özellik seti değil, para ve güven ilişkisinin zaman içine yayılmasıdır. B2C'de para siparişle birlikte gelir ve ilişki orada biter. B2B'de sipariş, teslimat, fatura ve tahsilat ayrı zamanlara dağılır; bu dağılmayı düzgün modellemezseniz, ne kadar şık bir vitrin kurarsanız kurun kurumsal müşteri telefonu açıp o eski usul teklif ve mutabakat trafiğini geri getirir.

Somut tavsiyemiz şu: bir B2B platformu kuruyorsanız işe cari hesabı bir defter olarak tasarlamakla başlayın. Bakiyeyi saklamayın, hareketlerden hesaplayın; parayı tam sayı kuruş tutun; özel fiyatı ürünün üzerine değil, fiyat motorunun en son katmanına bir kural olarak bağlayın; kredi limitini mevcut bakiyeyle değil, açık siparişleri de katarak yönetin; ve tekrar siparişte konfigürasyonu kopyalayın ama fiyatı asla dondurmayın. Bu beş karar birbirini besler ve hepsinin altında tek bir ilke yatar: gerçeğin kaynağı hareketlerdir. Defteri doğru kurarsanız, cari hesap da vade de faturalama da o defterin üzerine sakince oturur. Yanlış kurarsanız, her ay sonu aynı mutabakat kavgasını yeniden yaşarsınız.

Benzer bir altyapı mı kuruyorsunuz? Deneyimimizi projenize taşıyalım — 1 iş gününde teklif.
Teklif Al
yazilim.tech © 2026 yazilim.tech — Fikirden ürüne. Bir diji.tech markasıdır.