Satış alanı detayı
Alan haritası'ndaki Satış alanı (catalog, basket, purchase, buyer, buyer-group, post, price-analytics) self-servis vitrini kapsıyor. Bu sayfa ek bir boyutu detaylandırıyor: müşteri ile satışa dair mesajlaşma — bugün message modülünde yaşıyor ama Satış'a ait mantığı barındırıyor.
Mesajlaşma mimarisi: context registry
message modülü tek başına hangi domain'e ait olduğunu bilmiyor — bunun yerine bir resolver registry kullanıyor: her domain, kendi ConversationContextType değeri için ConversationContextRegistry'ye bir resolver kaydediyor (onModuleInit ile). Bir konuşma başlatıldığında message modülü ilgili resolver'ı çağırıp yetkilendirme + katılımcı listesini alıyor, kendi modülünü domain'e import etmeden. Bu, döngüsel bağımlılığı önleyen iyi bir tasarım — Alan haritası'ndaki yoğun forwardRef sorununun tam tersi bir çözüm.
ConversationContextType kapsamı
| Tür | Resolver var mı? | Durum |
|---|---|---|
RETURN | Var — order/services/return-conversation.resolver.ts | İade talebiyle ilgili konuşma; BuyerOrderReturn.conversationId'ye geri yazıyor. |
PRODUCT | Var — catalog/services/product-conversation.resolver.ts | Alıcı başına tek, kalıcı "Ürün Talepleri" konuşması; destek yetkilisine yönleniyor. |
SUPPORT | Yok — registry'den değil, message.service.ts içinde doğrudan (hardcoded) işleniyor | Genel destek hattı, herhangi bir domain'e bağlı değil. |
TEAM | Yok — aynı şekilde message.service.ts içinde özel durum | İç ekip sohbeti, muhtemelen customer-facing değil. |
ORDER | Yok — hiçbir yerde | Enum'da tanımlı ama kodun hiçbir yerinde kullanılmıyor. Ölü değer. |
Eksiklikler
ORDERcontext'i tamamen ölü. Bir alıcının belirli bir siparişi hakkında mesajlaşabileceği bir yol yok — sadece genelSUPPORThattı var. Sipariş bazlı mesajlaşma (ör. "bu ürün eksik geldi", "teslimat ne zaman") bugün ya SUPPORT'a düşüyor ya da hiç yapılamıyor.ProductRequest(katalog: "bu ürünü ekleyin" talebi) ilePRODUCTkonuşması aynı isimde ama farklı iki şey, sadece servis çağrısı seviyesinde bağlı:product-request-buyer.service.ts, talep oluşuncaPRODUCTkonuşmasına bir sistem mesajı yazıyor (getOrCreateProductConversation+createSystemMessage) — amaProductRequestşemasındaconversationIdgibi kalıcı bir alan yok. Konuşmayı bulmak için her seferinde alıcı id'siyle yeniden çözümleniyor.Conversation.contextIdbilinçli olarakstring(registry deseni döngüsel bağımlılığı önlemek için böyle tasarlanmış) — ama bu da Sipariş taraf ilişkileri'ndeki Invoice/Financial'daki gevşek referans sorununun bir başka örneği. Farkı: burada en azından tek bir tutarlı desen (registry + resolver) var; Invoice ve Financial'da öyle bir desen bile yok, her biri kendi başına gevşek.basket,purchase,post,price-analytics,buyer-groupmesajlaşmayla hiç temas etmiyor. Sepette takılı kalan bir alıcıya proaktif mesaj, checkout sırasında soru sorma gibi bir akış bugün yok.
Çalışan (destek yetkilisi) tarafı
Buraya kadarki bölüm alıcının gördüğü tarafı anlatıyor. Konuşmayı gerçekten yürüten destek yetkilisi (officer/admin) tarafında da somut boşluklar var:
- Atama bir kuyruk değil, kura.
getSupportOfficersForBuyer: alıcınınAdminBuyerOfficerüzerinden atanmış bir yetkilisi varsa o kullanılıyor; yoksaMath.random()ile pazarlama yetkilileri arasından rastgele bir kişi seçiliyor. Yük dengeleme, müsaitlik/online durumu, uzmanlık bazlı yönlendirme yok. - "Join" bir "claim" değil.
POST conversation/:id/joinherhangi bir officer/admin'in herhangi bir (private olmayan) konuşmaya katılmasına izin veriyor — sahiplenme/kilitleme yok. Birden fazla yetkili aynı konuşmaya girebilir, ya da hiçbiri girmeyebilir; zorlayıcı bir mekanizma yok. - Kuyruk/iş yükü görünürlüğü yok.
GET conversations,notParticipant: trueile "içinde olmadığım konuşmaları" listeleyebiliyor, ama bir durum alanı (ör. "atanmadı", "işleniyor", "çözüldü") yok — sıralama sadeceupdatedAt. Yetkili, neyin dikkat beklediğini listeye bakıp gözle ayırt etmek zorunda. - Company/warehouse kapsaması yok. Officer/admin, platform genelindeki her private-olmayan konuşmayı görüp katılabiliyor — Şirket, depo, sipariş hiyerarşisi'nde planlanan çalışma izniyle hiç bağlantısı yok. Bugün B deposunda çalışan bir yetkili, A deposunun bir alıcısının SUPPORT konuşmasını da görüp katılabilir.
- SLA/performans ölçümü yok. İlk yanıt süresi, çözüm süresi, yetkili başına açık konuşma sayısı gibi hiçbir metrik tutulmuyor (
AdminBuyerFeedbackHistoryalıcı ilişkisinin genel sağlığını tutuyor, ama mesajlaşmaya özgü değil).
Sınıflandırma gerilimi
message modülünün kendisi (Conversation/Message CRUD, registry, AI auto-reply) gerçekten ortak/çekirdek altyapı — Alan haritası'ndaki sınıflandırma doğru. Ama PRODUCT ve (kurulacaksa) ORDER resolver'ları satış mantığı — bunlar zaten catalog ve order modüllerinde yaşıyor (resolver dosyaları oradan registry'ye kayıt oluyor), message'ın kendisinde değil. Yani bu zaten doğru yerde: Satış'a ait mesajlaşma mantığı, Satış modüllerinin içinde; sadece ortak taşıyıcı altyapı (message) paylaşılıyor. admin/report gibi başka bir "hem ortak hem domain'e özel" gerilimi değil — burada zaten çözülmüş bir desen var.
Öneri
ORDERcontext'i için bir resolver eklenmeli (muhtemelenordermodülünde,return-conversation.resolver.ts'e paralel) — ya da enum'dan tamamen kaldırılıpSUPPORT'a devredilmeli. İkisinden biri: ölü kod olarak kalmamalı.ProductRequest'econversationIdalanı eklenmeli — bugünkü dolaylı (buyer id'sinden yeniden çözme) yaklaşım yerine doğrudan referans.- Konuşmaya bir atanan yetkili (
assignedOfficerId) ve bir durum (ör.UNASSIGNED/IN_PROGRESS/RESOLVED) alanı eklenmeli — "join" kuralı bu ikisinin yerini tutmuyor. - Konuşma görünürlüğü, çalışma izni (Company/Warehouse kapsamı) devreye girince ona göre daraltılmalı.
Sıradaki adım
Bu bulgular hedef modül şeması planlanırken Alan haritası'ndaki Satış tablosuyla ve Sipariş taraf ilişkileri'ndeki gevşek referans temasıyla birlikte ele alınacak.