EYDefterEmre Yakut
← tüm yazılar
Portal · Sistem · derin

Faturayı gösteren portalı sıfırdan yazdım

Apartmanda oturan biri ısı faturasını görmek istiyor. Basit gibi. Ama fatura başka bir sistemde, sayaç başka bir tabloda, taşınan kiracının geçmişi donması gerekiyor. Portalı bu yüzden sıfırdan yazdım.

CRM faturaların kaynağı sor cevap portal önbelleğe yazar sakin faturasını görür PULL: kaynak portalı hiç tanımaz — veri hiç farklılaşmaztaşınan kiracı: visible_from … visible_until → yalnız oturduğu dönemrelation_frozen = 1 → CRM’e BİR DAHA HİÇ SORULMAZfiltreyi biri unutur; yapılmamış bir sorguyu kimse unutamaz

Isı gider paylaşımında son halka şu: apartmanda oturan kişi eline bir fatura alıyor ve “bu rakam nereden çıktı?” diye soruyor.

Cevabı verecek yer bir portal. Eskisi vardı ama on yıllık bir e-ticaret altyapısının üstüne kurulmuştu ve her yeni istek onu biraz daha zorluyordu. Sıfırdan yazdım: app.brunatazenner.tr.

Ne gösteriyor

  • Faturalar — kalem kalem: ısı payı, ortak alan, su, sabit gider. PDF olarak da indirilebiliyor.
  • Günlük tüketim grafiği — sayaç okumaları, üstüne o günün hava sıcaklığı. İkisi yan yana olunca “kış soğuktu” cümlesi bir iddia olmaktan çıkıp grafiğe dönüşüyor.
  • Bina ortalaması kıyası — sen mi çok harcadın, bina mı. Gelen soruların yarısı bu kutuyla bitiyor.
  • İstek/öneri — mesajlaşmalı basit bir talep sistemi.
  • Hane alt kullanıcıları — eşin, çocuğun da kendi girişiyle bakabilsin.

Bir de ayrı bir site yöneticisi paneli var: blok ve haneler, sakinlere toplu SMS, duyurular, gelen istekler.

Asıl mimari karar: PULL

Faturalar portalda üretilmiyor. CRM’de üretiliyor — dönem dönem, kendi veritabanlarında.

İki seçenek vardı:

PUSHPULL
NasılCRM fatura onaylanınca portala gönderirPortal ihtiyaç duyunca CRM’e sorar
CRM’in portalı bilmesigerekirgerekmez
Portal kapalıykengönderim kaybolur, kuyruk gerekirhiçbir şey olmaz
Veri farklılaşmasızamanla kaçınılmazkaynak her zaman doğru

PULL’u seçtim. Portal bir fatura listesine ihtiyaç duyduğunda CRM’in ucuna gidiyor, cevabı alıyor ve kendi tablosuna yazıyor (cache-aside). Bir sonraki sefer önbellekten okuyor.

Önbellek tazelenirken de “ekle” değil “sil ve yeniden yaz” yapıyor. Sebep: bir fatura CRM’de iptal edilmişse, ekleme mantığı onu portaldan asla silmez. Sakin, iptal edilmiş bir faturayı aylarca görmeye devam eder.

Taşınan kiracı problemi

En çok kafa yorduğum kısım burası ve teknik değil, etik bir problem.

Bir kiracı Mart’ta taşınıyor. Şubat faturasını görebilmeli — o dönem orada oturuyordu, parayı o ödedi. Ama Nisan faturasını görmemeli; o daire artık başkasının ve orada başkasının tüketimi var.

İki mekanizmayla çözdüm:

ilişki: kullanıcı ↔ hane
  visible_from   = taşınma tarihi
  visible_until  = çıkış tarihi        ← sonrası görünmez
  relation_frozen = 1                  ← CRM'e artık SORMA

Görünürlük penceresi hangi dönemleri görebileceğini belirliyor. Donmuş ilişki ise daha sert bir şey: sistem o ilişki için CRM’e bir daha hiç gitmiyor, yalnız o güne kadar önbellekte olanı gösteriyor.

İkincisi olmasa, bir hata veya bir yanlış eşleşme yüzünden eski kiracı yeni kiracının verisini görebilirdi. Donmuş ilişkide bu fiziksel olarak mümkün değil — sorgu hiç yapılmıyor.

buradaki ilke

Yetkilendirmeyi “göster/gösterme” filtresi olarak kurmak yetmez. Asıl güvenli olan, veriyi hiç getirmemek. Filtreyi biri unutur; yapılmamış bir sorguyu kimse unutamaz.

Teknoloji tarafı

Hazır bir çatı kullanmadım ama her şeyi de yazmadım. Üç parça aldım, gerisini kendim yazdım:

yönlendirme : nikic/fast-route
şablon      : Twig
veritabanı  : PDO + ince bir sarmalayıcı
PDF         : mpdf  (faturayı yapısal veriden basıyor, HTML ekran görüntüsünden değil)
env         : phpdotenv  (sırlar web kökü dışında)

Eski veritabanı aynen kullanılıyor. Tablo adları, prefix, hatta eski parola özetleme yöntemi korundu — kullanıcılar eski şifreleriyle giriyor, ilk girişte sessizce modern özete geçiyorlar. Bir portalı yenilerken kimsenin şifresini sıfırlamak zorunda kalmamak, düşündüğünden büyük bir kazanç.

Ve bir demo modu

Portalı satış görüşmesinde göstermek gerekiyor. Gerçek bir sakinin faturasını açamazsın.

Bu yüzden /demo var: dolu bir hesap — 24 aylık tüketim, üç lokasyon, gerçekçi faturalar. Tamamı üretilmiş veri, ve demo hesabı CRM’e hiç gitmiyor (donmuş ilişki mekanizmasının ikinci kullanım alanı bu oldu).

Ne öğrendim

Bir portalın zor kısmı ekranlar değil. Zor kısım kimin neyi görebileceği — ve o soru neredeyse hiçbir zaman “rol” ile çözülmüyor. Zamanla, taşınmayla, iptalle, düzeltmeyle değişiyor.

Bu yüzden görünürlüğü bir tarih aralığı olarak modellemek, benim için bu projenin en değerli kararı oldu.

PortalSistem