Hamsayeh: binaları ve konut sitelerini yönetmek için bir SaaS

Hamsayeh («همسایه», Farsça "komşu") kendi ürünüm: apartmanları ve konut sitelerini yönetmek için bir SaaS. Yöneticiler, yönetim kurulu üyeleri, kat malikleri ve sakinler onu aidatlar, ödemeler, talepler ve duyurular için kullanıyor; sistem yöneticilerine ise ayrı bir portal hizmet veriyor. Mimarisini tasarladım ve hem backend'de hem front end'de kodun büyük bölümünü yazdım; birkaç kişi daha onboarding verilerinin kalıcı olarak saklanması ve İngilizce yerelleştirme gibi daha küçük parçalarla katkıda bulundu.

Bağlam

Birçok binada aylık aidat bir elektronik tabloda ya da bir defterde tutulur, ödemeler mesajla teyit edilir, duyurular da bir grup sohbetine gönderilir. Ürün bunun yerine tek bir sistem koyuyor: her tutarın izlenebildiği, sakinlerin kendi bakiyelerini ve taleplerini gördüğü, yöneticinin de daha az elle defter tuttuğu bir sistem. İş, temel bir MVP'den (giriş, binalar, aidatlar ve ödemeler) başlayıp finans, hizmetler, yönetişim ve büyüme aşamalarına uzanan ürün fazları halinde planlanıyor.

Mühendislik problemi

Bir bina uygulaması dışarıdan basit görünür. Dört şey işi zorlaştırır:

  • Roller binaya bağlıdır. Bir kişi sistemin sıradan bir kullanıcısı, bir binanın yöneticisi ve başka bir binada kiracı olabilir. Sistem rolleri ile bina rollerinin (yönetici, yönetici yardımcısı, kat maliki, kiracı, sakin) birbirinden ayrı tutulması ve her isteğin ilgili olduğu binaya göre denetlenmesi gerekir.
  • Hesabın tutması gerekir. Aidatlar, ödemeler, cezalar, indirimler, taksitler, fonlar, giderler ve bütçeler, bir dairenin borcunu etkiler. Bir rakam açıklanamıyorsa sakinler sisteme güvenmeyi bırakır.
  • Özellik listesi uzundur. Muhasebe, talepler, rezervasyonlar, oylama, abonelikler ve bir pazaryeri aynı anda büyür. Sıkı sınırlar olmadan hepsi, kimsenin güvenle değiştiremeyeceği tek bir veri modeline çöker.
  • Kullanıcıların çoğu telefondadır. Arayüz öncelikle Farsça ve sağdan sola tasarlanır; telefonda da masaüstünde olduğu kadar iyi çalışmalıdır.

Geliştirdiklerim

Backend'de biri bina kullanıcıları, diğeri sistem yönetimi için olmak üzere iki ASP.NET Core API host'u var; ikisi de FluentValidation ile doğrulanan MediatR komut ve sorgularından oluşan ortak bir uygulama katmanının üzerinde çalışıyor. Ana alanlar:

  • Giriş ve oturumlar. Cep telefonu numarasına gönderilen tek kullanımlık kodlar, yenileme oturumları, ikinci faktör doğrulamalı parolayla giriş ve birden fazla role sahip kişiler için portal geçişi. Başarısız denemeler sayılır ve geçici bir engellemeye yol açar.
  • Onboarding. Bina oluşturma, daire ekleme, yöneticileri ve yönetim kurulu üyelerini davet etme ve bir davetle binaya katılma.
  • Muhasebe. Aidat dönemleri, çevrim dışı ve çevrim içi ödemeler, ödeme bağlantıları, fonlar, giderler, bütçeler, alacaklar ve taksit planları, ceza ve indirim kuralları, borçlu yaşlandırma, kâr ve zarar, daire ekstreleri ve CSV ile PDF rapor dışa aktarımları.
  • Bina operasyonları. SLA takipli talepler (ticket), duyurular (zamanlanmış olanlar dahil), ortak alan rezervasyonları, belgeler, demirbaşlar ve oylamalı toplantılar. Arka plan servisleri talep SLA'larını, zamanlanmış duyuruları, ceza kurallarını ve dışa aktarılan raporların saklanma süresini yönetir.
  • Sistem yönetimi. Kullanıcılar, organizasyonlar, abonelik planları, referanslar, bir pazaryeri, operasyon ekranları ve denetim kaydı.

Front end, Vite, TypeScript, MUI ve TanStack Query ile React 19 üzerine kurulu ve bir admin portalı ile bir bina portalına ayrılıyor. Capacitor aynı uygulamayı Android için paketliyor.

Tasarım notları

Modüler monolit, her alan için bir şema

Backend, iç sınırları olan tek bir kod tabanı; iki API host'u olarak deploy ediliyor. PostgreSQL veritabanı şemalara ayrılmıştır (kimlik, bina, muhasebe, yönetişim, büyüme, hizmet ve pazaryeri) ve her şema kendi EF Core DbContext'iyle eşlenir. Muhasebe bir adım daha ileri gider: kendi domain, application ve infrastructure projeleri vardır ve binalara ve dairelere hiçbir zaman bir EF navigation property üzerinden değil, id'leri ve adın ya da daire numarasının saklanan bir anlık görüntüsü üzerinden başvurur. Bu, bugün dağıtık transaction'ların bedelini ödemeden ileride bir ayrışmayı mümkün kılar. Mimari testler kuralları zorunlu kılar: muhasebe domain'i hiçbir dış katmana referans vermez, muhasebe entity'leri başka alanlara navigation yapmaz ve uygulama kodu zamanı bir saat soyutlaması (clock abstraction) üzerinden okur.

Hiç düzenlenmeyen bir defter

Finansal olaylar deftere çift taraflı yevmiye kayıtları işler. Bir aidat tahakkuku alacak hesaplarını borçlandırır ve aidat gelirini alacaklandırır; bir ödemenin onaylanması kasa ya da bankayı borçlandırır ve alacakları alacaklandırır; bir ceza alacakları borçlandırır ve ceza gelirini alacaklandırır. En az iki satırı yoksa ve borçları alacaklarına eşit değilse bir yevmiye kaydı reddedilir; deftere işlendikten sonra da değişmez: düzeltme yeni bir ters kayıttır. Finansal listeler ve raporlar filtreleme, sıralama, sayfalama ve toplama işlemlerini bellekte değil, veritabanında yapar.

Denetim kaydı kendi veritabanında

Bir middleware her API çağrısını (işlemi yapan, rol, metot, path, durum, süre ve istek gövdesi) ayrı bir PostgreSQL veritabanına kaydeder. Kimlik doğrulama çağrılarının gövdeleri bir maskeleme işaretiyle değiştirilir; denetim kaydının yazılamaması ise isteği başarısız kılmadan loglanır. Ayrı tutulan denetim verisi ana veritabanına yük olmadan büyür ve sistem yöneticileri onu filtreleyerek yalnızca finansal değişiklikleri görebilir.

Bağımlılık değil, yardımcı olarak Redis

Redis, önbelleğe alınmış dashboard verilerini ve giriş denemelerini sınırlayan sayaçları tutar. Her önbellek işlemi best-effort esasıyla yapılır: Redis erişilemezse okuma önbellekte bulunamamış (miss) sayılır, yazma atlanır; böylece API yalnızca veritabanıyla çalışmaya devam eder.

Test ve CI

  • Backend'de, ASP.NET Core'un test host'u üzerinden çalışan API testleri ve yukarıdaki mimari testler dahil yaklaşık 390 xUnit test metodu.
  • Front end'de yaklaşık 100 Vitest test dosyası; ayrıca import'ların portal sınırlarını aşmasını engelleyen ve route'larla navigasyonu senkron tutan özel kontroller.
  • Her rol, portallar arası erişim ve mobil sağdan sola yerleşim için Playwright kullanıcı yolculukları; küçük bir bina senaryosu süiti CI'da tam Docker Compose yığınına karşı çalışır. Bir Locust süiti ana yolculukları yük testinden geçirir.
  • GitHub Actions ile backend CI (format kontrolü, uyarıların hata sayıldığı build, testler), front-end CI, Docker imaj build'leri, C# ve TypeScript için CodeQL analizi ve bir Android debug APK build'i.

Teknoloji yığını

  • .NET 10, ASP.NET Core, EF Core, MediatR, FluentValidation
  • PostgreSQL 17 (ana ve denetim veritabanları)
  • Redis 7.4
  • React 19, Vite, TypeScript, MUI, TanStack Query, Capacitor
  • xUnit, Vitest, Testing Library, Playwright, Locust
  • Docker Compose, GitHub Actions

Durum

  • Hamsayeh aktif olarak geliştiriliyor. Tüm yığın (iki API, web uygulaması, iki PostgreSQL instance'ı ve Redis) Docker Compose ile ayağa kalkıyor ve asgari ya da demo veri yükleyebiliyor.
  • Çevrim içi ödemeler şimdilik bir sandbox akışından geçiyor. Projenin production öncesi kendi iş listesinde sıkılaştırılmış production yapılandırması, ödeme ve bildirim yan etkileri için bir outbox, kalıcı dosya depolama ve loglardaki hassas verilerin daha sıkı maskelenmesi yer alıyor.

İlgili

Çok kiracılı mikroservis platformu diğer yolu izliyor: ayrı servisler ve veritabanında kiracı izolasyonu. .NET üzerinde bir SaaS ürünü planlıyorsanız Benimle çalışın sayfasına bakın.

Sık sorulan sorular

Hamsayeh nedir?

Hamsayeh, Mahdi Molavi'nin apartmanları ve konut sitelerini yönetmek için geliştirdiği kendi SaaS ürünüdür. Daireleri ve sakinleri, aidatları, ödemeleri ve muhasebeyi, talepleri, duyuruları, rezervasyonları, belgeleri ve toplantıları kapsar; bina kullanıcıları ve sistem yöneticileri için ayrı portalları vardır.

Hamsayeh hangi teknolojileri kullanıyor?

Backend, PostgreSQL 17 üzerinde ASP.NET Core, EF Core ve MediatR ile .NET 10'dur; denetim kaydı için ayrı bir PostgreSQL veritabanı, önbellek için Redis kullanılır. Front end, Vite, TypeScript, MUI ve TanStack Query ile React 19'dur ve tüm yığın Docker Compose ile çalışır.

Hamsayeh finansal kayıtlarını nasıl tutarlı tutuyor?

Muhasebe, çift taraflı kayıt defterine sahip ayrı bir modüldür. Bir yevmiye kaydının, borç ve alacak toplamları eşit olan en az iki satırı olmalıdır; deftere işlenmiş bir kayıt asla düzenlenmez, düzeltme yeni bir ters kayıttır.

Mahdi Molavi'nin rolü neydi?

Mimariyi tasarladı ve hem backend'de hem front end'de kodun büyük bölümünü yazdı. Birkaç kişi daha onboarding verilerinin kalıcı olarak saklanması ve İngilizce yerelleştirme gibi daha küçük parçalarla katkıda bulundu.

Hamsayeh tamamlandı mı?

Hayır. Aktif olarak geliştiriliyor. Tüm yığın Docker Compose ve demo verilerle çalışıyor, çevrim içi ödemeler bir sandbox akışı kullanıyor ve projenin production öncesi kendi iş listesinde yan etkiler için bir outbox, kalıcı dosya depolama ve sıkılaştırılmış production yapılandırması yer alıyor.

Bu bölümdeki diğer sayfalar

Projeler