Saha modülü, kapsama alanı dışında çalışan bayi ve saha temsilcilerinin tahsilat kaydetmesi içindir. Android uygulaması kayıtları ağ beklemeden cihazdaki kuyruğa yazar; bağlantı gelince toplu senkron eder. Tasarımın omurgası tek ilkedir: cihaz beyan eder, sunucu karar verir.

İki zaman, iki otorite

Her tahsilat kaydında iki zaman kolonu vardır ve karıştırılmaları yasaktır: Aradaki fark sapma olarak saklanır; üç günü aşan sapmalar kayıt reddedilmeden kabul edilir ama gün sonu raporunda “saati bozuk” sayacında ayrıca görünür.

Senkron protokolü

Protokolün kuralları:
  • Cihaz bağı: temsilci ilk senkronda cihazına otomatik bağlanır; başka cihazdan gelen senkron 409 field.device_mismatch alır. Cihaz değişimi için paneldeki “Cihazı bırak” aksiyonu (gerekçe zorunlu) kullanılır.
  • Idempotency: her işlemin cihazda üretilmiş bir clientOpId’si vardır. Yeniden gönderim yeni kayıt açmaz; sunucu duplicate der ve ilk kaydın kimliğini döner. Aynı kimlikle farklı içerik gelirse kayıt değişmez — çelişki, kaydın üzerine device_claims olarak eklenir: çelişkinin kendisi kanıttır.
  • Zehirli kayıt partiyi düşürmez: geçersiz bir işlem (rejected + gerekçe) kalıcı olarak reddedilir ama partinin kalanı işlenir.
  • serverTime yanıtta döner: cihaz kendi sapmasını hesaplayıp temsilciyi uyarır (“telefon saatiniz 12 dk geride”) — ama sistem saatini değiştirmez.

Para durumunu yalnız sunucu yazar

Cihaz yalnız iki durum üretebilir: talep kaydedildi ve nakit beyanı. succeeded durumunu cihaz asla yazamaz:
  1. Kabul edilen karta/QR’a dayalı işlemler için sunucu bir ödeme bağlantısı üretir (link_issued).
  2. Müşteri öder; bağlantının sonucunu iki dakikalık bağlantı işi defterden kapatır.
  3. Beş dakikalık saha işi, bağlantısı kapanan kayıtları succeeded/failed yapar. Temsilcinin telefonu kapansa, uygulama silinse, cihaz kaybolsa bile tahsilat doğru kapanır.
Nakit beyanı ayrı tutulur. cash_declared hiçbir zaman succeeded olmaz; gün sonu raporu üç toplamı ayrı verir — kesinleşen (gerçekten tahsil edilen), nakit beyanı (kasaya teslim edilmeli, mutabakata girmez) ve bekleyen. Tek toplamda birleştirmek, hiç görmediğimiz parayı tahsil edilmiş göstermek olurdu.

Cihaz uygulaması

Android uygulaması bilinçli olarak tek ekrandır: tutar (yalnız rakam girişi — kuruş sağdan dolar, çünkü Android sayısal klavyesi virgülü sessizce yutar ve nokta yüz katlık tutar hatası üretir), yöntem seçimi (bağlantı / karekod / nakit beyanı) ve bekleyen kayıt listesi. Kaydet düğmesi ağ beklemez; senkron arka planda denenir. Ağ yoksa mesaj nettir: “Ağ yok — kayıtlar cihazda bekliyor, kaybolmadı.” İstemci kuyruğunun kuralları sunucuyla simetriktir: accepted ve duplicate aynı şekilde kuyruktan düşer (ayırmak, yeniden gönderilen kaydı sonsuza dek kuyrukta bırakırdı); rejected kuyruktan çıkar ama silinmez; bilinmeyen sonuç kuyrukta kalır — sunucu yeni bir sonuç türü eklerse eski cihaz kayıt kaybetmez. Ağ ve sunucu hataları (4xx dahil) kayıt silmez: yanlış bir 4xx yüzünden günün tahsilatını silmek, beklemekten çok daha pahalıdır. Düz HTTP cihazda yasaktır (yalnız geliştirme istisnaları); uygulama yedeği kapalıdır — yedekten dönen eski kuyruk, ödenmiş tahsilatları yeniden göndermeye çalışırdı.

Panel ve yetkiler

Panelin Saha sayfası gün seçimli gün sonu özetini (temsilci × bölge), temsilci listesini ve tahsilat kayıtlarını gösterir — cihaz beyanı ile sunucu zamanı ayrı kolonlardadır. Temsilci yönetimi (ekleme, cihaz bırakma, kapatma) Admin, senkronun kendisi Operasyon yetkisidir: kimin şirket adına para toplayacağına karar vermek yönetim işidir, sahada senkron etmek sahanın işi. Temsilci silinmez, kapatılır; tahsilat kayıtları veritabanı düzeyinde silinemez.