İçeriğe geç

Vaka çalışmasıYayında

Tahsil

Türk KOBİ’leri için alacak ve tahsilat yönetimi: cari hesaplar, faturalar, nazik hatırlatma akışları, ödeme linki ve mutabakat — her zaman denk tutan çift taraflı bir defter üzerinde.

Rol
Tek başıma — ürün, tasarımın uygulanması, backend, altyapı
Ne zaman
2026
  • Backend
  • Full-stack

“Demoyu aç” demo şirket Ege Tekstil’i üye olmadan açıyor. Linki test kartı 4242 4242 4242 4242, son kullanma 12/30, CVC 123, 3-D Secure kodu 123456 ile öde. Veriler her gece 04:00’te sıfırlanıyor; kaynak kod gizli.

Demo şirket Ege Tekstil için Tahsil’in genel bakışı: ₺2.318.695,40 toplam alacak, ₺746.460 vadesi geçen, 90 günlük tahsilat oranı %89,9, yaşlandırma grafiği ve bugünün işleri.
Genel bakış: alacaklar, vadesi geçenler, yaşlandırma ve bugünün işleri.

Kimin için

  • İzmir’de yaklaşık 50 kurumsal müşterisi ve ₺2,4 milyon açık alacağı olan bir tekstil toptancısı. Bugün: Excel’de bir yaşlandırma tablosu, müşterileri telefonla arayan bir finans müdürü, çekmecede çekler ve gözle eşleştirilen banka ekstreleri.
  • İhtiyaçları belli: her zaman tutan, müşteri başına bir cari hesap; zamanında giden ve para gelince kendiliğinden duran hatırlatmalar; müşterilerin kartla taksitli ödeyebileceği bir link.
  • Onların müşterileri: linki açıp tamamını ya da bir kısmını kartla — taksitli, 3-D Secure ile — ya da açıklamaya fatura numarasını yazarak EFT ile ödüyorlar.

Ne yaptım

  • Cloudflare’ın ücretsiz planında tek bir Worker olarak tek başıma kurdum: Hono API, kayıt sistemi olarak D1 ve SQLite tabanlı üç Durable Object sınıfı — şirket başına bir hatırlatma zamanlayıcısı, ödeme sağlayıcısının webhook’larını teslim eden bir giden kutusu ve gece sıfırlamasını parça parça yapan bir bakım nesnesi.
  • Tek Düzen Hesap Planı üzerinde çift taraflı bir defter: her para olayı — fatura, tahsilat, iade, iade faturası, silme, avans mahsubu — tek bir transaction’da tek bir dengeli yevmiye kaydı. Bakiyeler, yaşlandırma, ekstreler ve DSO yevmiye satırları üzerinden toplam; tutarlar baştan sona tam sayı kuruş.
  • Onaylanmış bir tasarımdan aktarılan React + Vite arka ofis: cari hesaplar ve ekstreler, olay geçmişli e-Fatura tarzı faturalar, hatırlatma akışı editörü (e-posta, SMS, WhatsApp), tahsilatlar ve mutabakat inceleme kuyruğu, Excel dışa aktarımlı raporlar, roller ve ayarlar — ayrıca taksitli ve 3-D Secure’lü herkese açık ödeme linki sayfası.
  • Tek bir yerde zorlanan multi-tenancy, beş rollü PBKDF2 kimlik doğrulama, imzalı webhook’ları iki üç kez ve sırasız gönderen iyzico benzeri sahte bir PSP’yle PaymentProvider arayüzü — ve değişmezleri kanıtlayan özellik testi, webhook tekrar testi ve yük testi.

Nasıl çalışıyor

  1. 1Faturala

    Fatura içe aktarılıyor ya da taslaktan gönderiliyor: tek bir dengeli yevmiye kaydı — alıcılar borç, satışlar ve KDV alacak — ve müşteriye bir ödeme linki gidiyor.

  2. 2Hatırlat

    Carinin akışı (vadeden 3 gün önce, vade günü, +7, eskalasyonlu +14) şirketin seçtiği saatte, Europe/Istanbul’a göre çalışıyor — gece, hafta sonu ve resmî tatillerde asla; eskalasyon adımları bir arama görevi açıyor.

  3. 3Öde

    Müşteri linki açıp tamamını ya da bir kısmını 3-D Secure adımıyla kartla taksitli ödüyor — ya da açıklamaya fatura numarasını yazıp EFT yapıyor.

  4. 4Mutabakat

    Webhook’lar (iki üç kez, sırasız gelen) ve banka hareketleri faturalarla eşleşiyor: kesin referanslar otomatik işleniyor, bulanık olanlar güven skoruyla inceleme kuyruğunda bekliyor. Fazla ödeme cari avansa dönüyor.

  5. 5Dur ve raporla

    Tamamen ödenen fatura bekleyen hatırlatmalarını iptal ediyor; yaşlandırma, tahsilat oranı ve DSO doğrudan yevmiyeden geliyor ve Excel’e aktarılıyor.

Önemli kararlar

  1. 01

    Bakiyeler hiçbir zaman saklanmıyor

    Yerine: Her fatura ve caride, para hareket ettikçe güncellenen bir bakiye sütunu.

    Neden: Her para olayı tek bir D1 batch’i — tek bir SQLite transaction’ı — olarak bir yevmiye başlığı ve satırlarından oluşuyor. Kalan tutarlar, cari avans, yaşlandırma ve ekstreler satırlar üzerinden toplam. Yevmiye yalnızca ekleniyor; her batch’in içindeki bir koruma satırı, borcu alacağına eşit olmayan bir kaydı veritabanının kendisine reddettiriyor.

  2. 02

    Kısıtla tam bir kez, dağıtım transaction’ın içinde

    Yerine: Ödeme görüldü mü diye bakıp sonra yazmak; işlerken faturayı kilitlemek.

    Neden: Her kayıt, olayının iş kimliğini unique bir kısıtla taşıyor; tekrar gelen olay bütün batch’i atomik olarak düşürüyor ve mükerrer olarak raporlanıyor. Faturaya işlenen tutar, ödeme ile kalan tutardan küçük olanı — aynı transaction’da SQL ile hesaplanıyor, kalanı cari avansa gidiyor — böylece iki eşzamanlı ödeme bir faturayı asla fazla kapatamıyor; kilit yok, oku-sonra-yaz aralığı yok.

  3. 03

    Zaman için Durable Object, doğruluk için D1

    Yerine: Her fatura için bir Workflow örneği.

    Neden: Şirket başına bir hatırlatma zamanlayıcısı çok günlük takvimi ve en erken iş için tek bir alarm tutuyor; alarm çaldığında göndermeden önce D1’i yeniden okuyor — ödendi mi, duraklatıldı mı — ve bir tahsilat da onu iptal için dürtüyor. Ücretsiz planda fatura başına bir Workflow, şirket başına bir alarm’a göre hiçbir şey kazandırmıyor ve iptali daha zor.

  4. 04

    Tenancy tek bir yerde

    Yerine: Her sorguya şirket filtresini eklemeyi hatırlamak.

    Neden: Her satır şirket kimliğini taşıyor; şirket verisine giden SQL’e yalnızca, kapsamı belirtilmemiş her ifadeyi reddeden bir veri katmanından ulaşılıyor. Testler başka şirketin verisini okumanın boş döndüğünü, yazmanın transaction içinde reddedildiğini kanıtlıyor; özellik testi bu katmana 50.226 böyle deneme gönderdi.

Mimari

İSTEMCILERBack officeReact · beş rolPay link/ode/:token · 3-DSecure · taksitBank linesEFT · havale · FASTHTTPS /api/* · imzalı webhookEDGECloudflare Workerstatik dosyalar · Worker yalnızca /api/*UYGULAMAHono API + Ledgerşirket kapsamlı DAL ·kapsamsız SQL’i reddederReminder DOşirket başına 1 · tekalarmPSP outbox DOwebhook 2–3× · yenidendenemetek batch = tek transactionVERID1çift taraflı yevmiye ·kayıt sistemiDO SQLitehatırlatma takvimleriDIŞ SERVISLERPaymentProvidersahte PSP · iyzicobenzeriChannelse-posta · SMS ·WhatsApp · yalnızca logCron 04:00parçalı gece demosıfırlama↑ yayına alırTESLIMATProperty test1.040.000 işlem ·üretim SQL’iWebhook replay11.619 teslimatLoad test16 kullanıcı · wranglerdevVitest31 test · unit +Workers runtime

Paranın tek doğruluk kaynağı D1; Durable Object’ler yalnızca zamanı tutuyor. Buradaki her şey benim.

Sayılar

rastgele işlem — defter dengede kaldı, her bakiye bağımsız bir yeniden oynatmayla tuttu
1.040.000
388 kart ödemesi için imzalı webhook teslimatı — her biri tam bir kez işlendi
11.619
yük altında mükerrer — 616 ödeme, 0 eksik, 0 yanlış tutar
0
aylık maliyet — Cloudflare’ın ücretsiz planı
0 €

Teknolojiler

Backend

  • Cloudflare Workers
  • Durable Objects
  • D1 (SQLite)
  • Hono
  • TypeScript
  • Cron Triggers
  • Rate Limiting
  • PBKDF2

Frontend

  • React
  • React Router
  • Vite

Ödeme ve muhasebe

  • Double-entry ledger
  • Idempotency keys
  • HMAC-SHA256 webhooks
  • 3-D Secure flow

Kalite

  • Vitest
  • vitest-pool-workers
  • node:sqlite property tests
  • Load test

Uzun versiyonu ister misin — kod, pipeline, ödünleşimler?

E-posta gönder
Sıradaki vaka çalışmasıMasaTürkiye’deki bağımsız kafe ve restoranlar için QR menü, masadan sipariş, mutfak ekranı, garson tableti ve işletme paneli.