# Haljet > Haljet platformunun yapıları, veri akışları ve veri modelleri. ## Alan haritası \[Bugünkü modüller hangi alana giriyor?] Bu sayfa bugün `src/modules` altında duran 27 modülü, hedeflenen dört alana ([v2 nedir?](/v2)) göre sınıflandırır. Amaç kod değiştirmek değil, **mevcut yapıyı yeni bir gözle haritalamak**. Her modülün ayrıntılı görevi için [Modül haritası](/structures) sayfasına bakın; burada sadece hangi alana ait olduğu ve varsa tartışmalı noktası var. ### Satış "Satış" burada bir insan satış ekibini değil, **self-servis mobil vitrini** ifade ediyor — alıcı kendi kendine `buyer` (mobil uygulama) üzerinden sipariş veriyor, aradan satış yapan biri yok. Satıştan doğan sorunlarla (iade, şikayet, sorun bildirimi) `admin`'in zaten sahip olduğu CRM/destek fonksiyonu ilgileniyor — bu yüzden "destek" ayrı bir alan değil, admin'in içinde. Bu alanın müşteriyle mesajlaşma boyutu (bugün `message` modülünde yaşıyor) ayrıca detaylandırıldı: [Satış alanı detayı](/v2/satis-detay). | Modül | Alana neden giriyor | Not | | ----------------- | ----------------------------------------- | --------------------------------------------------------------- | | `catalog` | Ürün, kategori, fiyat, arama — vitrin | HKS ürün kodu ve depo fiyatı lojistik tarafına da dokunuyor | | `basket` | Alıcının sepeti | — | | `purchase` | Sepetten sipariş oluşturma (checkout) | Oluşturduğu belge `order`'a yazılıyor | | `buyer` | Alıcı profili, adres | `buyer/warehouse` ekstre görünümü muhasebe verisini gösteriyor | | `buyer-group` | Alıcı segmentasyonu (ciro, sipariş adedi) | — | | `post` | Vitrin içerik: slider, banner, akademi | — | | `price-analytics` | Piyasa fiyat analitiği, ticker | Diğer modüllere bağımlı değil; admin analitiğine de sayılabilir | ### Lojistik Tedarik (`seller`/`procurement`) burada da bir insan satın alma ekibinin talebiyle değil, **talep odaklı** (pull) çalışıyor: depo ekibi, satıştan oluşan "alınacaklar listesi"ne göre satıcıdan tedarik kararı veriyor. Yani tedarik, satış verisine tepki veren bir lojistik fonksiyonu. | Modül | Alana neden giriyor | Not | | ------------- | -------------------------------------------- | ------------------------------------------------------------------------------- | | `warehouse` | Depo tanımı, kapsama alanı, araç, istatistik | Eski stok-in/out da burada yaşıyor | | `stock` | Yeni FIFO stok girişi/çıkışı | `warehouse` içindeki eski stok sistemiyle paralel çalışıyor — bkz. açık sorular | | `transfer` | Teslimat, araç seferi, kapıda tahsilat | — | | `procurement` | Satıcının tedarik talebi | Talep, satıştan oluşan "alınacaklar listesi"ne göre depo ekibince tetikleniyor | | `seller` | Tedarikçi kartı | Ödeme takvimi ve vergi sorgusu muhasebe tarafına dokunuyor | | `area` | Ülke, il, ilçe, mahalle | Adres olarak satışa, kapsama alanı olarak lojistiğe hizmet ediyor | ### Muhasebe | Modül | Alana neden giriyor | Not | | ----------- | ---------------------------------------------------------- | --- | | `financial` | Cari bakiye, hareket defteri | — | | `invoice` | Giden/gelen e-fatura kaydı | — | | `payment` | Ödeme sağlayıcı entegrasyonları (PayTR, Paywall, MagicPay) | — | ### Admin | Modül | Alana neden giriyor | Not | | --------- | ------------------------------------------- | ------------------------------------------------------------------- | | `admin` | Alıcı CRM, yetkili atama, platform ayarları | Üç ayrı iş tek modülde bir arada — bkz. açık sorular | | `officer` | Yetkili/personel yönetimi, konum, atama | Saha/teslimat operasyonu tarafı lojistiğe yakın — bkz. açık sorular | ### Ortak / çekirdek Aşağıdakiler hiçbir alana özgü değil; hepsi tarafından kullanılıyor. Alan bazlı yeniden yapılanmadan bağımsız, ortak katman olarak kalması beklenir. | Modül / klasör | Görevi | | ------------------------------------------------------------------------------- | --------------------------------------------------- | | `auth`, `user` | Kimlik, hesap | | `message`, `notification` | Sohbet ve bildirim altyapısı | | `ai` | Doğal dil asistanı | | `static` | Politika sayfaları | | `report` | Tüm alanlardan okuyan raporlama katmanı | | `workflow` | Depo bazlı genel iş takip panosu (alana özgü değil) | | `izibiz`, `hks`, `mail`, `sms`, `meilisearch`, `bigquery`, `firebase`, `gemini` | Dış sistem sarmalayıcıları | | `common`, `config`, `prisma`, `i18n` | Platform altyapısı | ### Özel durum: order `order` hiçbir alana tam olarak sığmıyor — çünkü sipariş, satışın sonucu, lojistiğin girdisi ve muhasebenin tetikleyicisi aynı anda. Bugünkü kodda da bunu yansıtır şekilde en çok modülü import eden, en çok modül tarafından import edilen modül `order`. ```mermaid flowchart TB subgraph Satis[Satış] Catalog[catalog] Basket[basket] Purchase[purchase] Buyer[buyer] end subgraph Lojistik[Lojistik] Warehouse[warehouse] Stock[stock] Transfer[transfer] end subgraph Muhasebe[Muhasebe] Financial[financial] Invoice[invoice] Payment[payment] end subgraph Admin[Admin] AdminMod[admin] Officer[officer] end Catalog --> Basket --> Purchase --> Order((order)) Buyer --> Order Order --> Warehouse Order --> Stock Order --> Transfer Order --> Financial Order --> Invoice Order --> Payment AdminMod --> Order Officer --> Order ``` Hedef yapı planlanırken `order`'ın tek bir alana taşınıp taşınmayacağı, yoksa dört alanın da okuyup yazdığı ortak bir "sipariş çekirdeği" olarak mı kalacağı ayrıca karara bağlanmalı. ### Açık sorular Hedef yapı planına geçmeden önce netleşmesi gereken noktalar: * **`order` nereye ait?** Tek alana taşınacak mı, yoksa ortak çekirdek olarak mı kalacak? (yukarıya bakın) * **`admin` üç ayrı işi taşıyor**: alıcı CRM, yetkili ataması, platform ayarları (şirket tipleri, test siparişi). Bunlar ayrışacak mı, tek "admin" alanında mı kalacak? * **`officer`**, personel yönetimi (admin) ile saha/teslimat operasyonu (lojistik) arasında bölünmüş durumda. * **`report`**, tanımı gereği tüm alanlardan okuyor; tek bir alana yazılamaz — muhtemelen ortak katman olarak kalmalı, alan bazlı alt sayfalar üretebilir. * **`seller`**, tedarikçi kartı olarak lojistik, ödeme takvimi/vergi sorgusu olarak muhasebe tarafını taşıyor. * **`area`**, adres ihtiyacı (satış/admin) ile kapsama alanı/bölge (lojistik) arasında paylaşılıyor. * **`price-analytics`** bağımsız duruyor; satışın fiyat zekası mı, admin'in analitik katmanı mı olacağı netleşmeli. * **İki paralel stok sistemi var**: `warehouse` içindeki eski stok-in/out ile `stock` modülündeki yeni FIFO sistemi aynı anda çalışıyor. v2'de birleştirilmesi düşünülmeli. * **Yoğun döngüsel modül bağımlılığı** (`order`, `officer`, `warehouse`, `buyer`, `transfer`, `financial`, `payment`, `catalog`, `admin` birbirini `forwardRef` ile çağırıyor) alan sınırları çizilirken kırılması gereken bir engel. Her sınır değişikliği cold-boot ile doğrulanmalı (tsc/eslint döngüsel kırılmaları yakalamıyor). * **`HksInvoiceTracker`** Prisma modeli şemada var ama kodda hiçbir yerde kullanılmıyor — ölü model mi, rezerve alan mı netleşmeli. Bu sorular, hedef yapı planı (bkz. [v2 nedir?](/v2)) yazılırken tek tek karara bağlanacak. ## v2 nedir? \[Yeniden yapılanma planı] Haljet API'nin genel kurgusu değişmiyor: tek bir API, aynı iş akışları, aynı roller. Değişecek olan **iç yapı** — modüllerin nasıl gruplandığı, sınırların nerede çizildiği ve bağımlılıkların ne kadar temiz olduğu. Amaç daha stabil, daha az kırılgan, daha kolay anlaşılır bir kod tabanı. Bu bölüm kod değişikliği içermez; **plan ve karar dokümanlarını** barındırır. Kod tarafındaki değişiklikler bu plan üzerinde hemfikir olunduktan sonra ayrı adımlarda yapılır. ### Süreç 1. **Mevcut durumun planı** — bugünkü 27 modülün hangi işi yaptığı ve hedef alanlardan hangisine karşılık geldiği çıkarılır. *(Bu bölüm: [Alan haritası](/v2/alan-haritasi))* 2. **Hedef yapının planı** — modüllerin dört alan etrafında nasıl gruplanacağı, sınırların nasıl netleşeceği ve tartışmalı modüllerin (bkz. açık sorular) nasıl çözüleceği kararlaştırılır. *(Başladı: [Şirket, depo, sipariş hiyerarşisi](/v2/sirket-depo-siparis))* 3. **Geçiş planı** — hangi modülün hangi sırayla taşınacağı, geriye dönük uyumluluk ve test/cold-boot doğrulama adımları. *(Henüz yazılmadı.)* Planlama sırasında ortaya çıkan, mevcut kodda karşılığı olmayan ihtiyaçlar ayrıca tutuluyor: [Yeni ihtiyaçlar](/v2/yeni-ihtiyaclar). ### Dört alan API tek kalıyor, ancak modüller iş alanına göre gruplanacak şekilde düşünülüyor: | Alan | Türkçe karşılığı | Kapsadığı iş | | ---------- | ---------------- | ---------------------------------------------------- | | `admin` | Yönetim | Platform yönetimi, personel/yetkili ataması, CRM | | `satış` | Satış | Katalog, sepet, satın alma, alıcı, pazarlama içeriği | | `lojistik` | Lojistik | Depo, stok, teslimat, tedarikçi, bölge | | `muhasebe` | Muhasebe | Cari, ödeme, fatura | Bu dört alan kesin ve kapalı bir liste değil — ileride yeni alanlar eklenebilir. Ama şu anki genel kurgu bunların etrafında şekilleniyor. Bazı modüller (`order` gibi) tek bir alana ait değil; birden fazla alana dokunuyor. Bu tür modüller [Alan haritası](/v2/alan-haritasi) sayfasında ayrıca işaretlendi — hedef yapı planlanırken bunlar için ayrı bir karar gerekecek. Mevcut modüllerin tek tek görevleri için [Modül haritası](/structures) sayfası geçerliğini koruyor; burada tekrarlanmıyor. ## Satış alanı detayı \[Vitrin, müşteri mesajlaşması ve destek yetkilisi] [Alan haritası](/v2/alan-haritasi)'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ı](/v2/alan-haritasi)'ndaki yoğun `forwardRef` sorununun tam tersi bir çözüm. ```mermaid flowchart LR Message[message modülü] -->|contextType'a göre sorar| Registry[ConversationContextRegistry] ReturnResolver[order: ReturnConversationResolver] -->|register| Registry ProductResolver[catalog: ProductConversationResolver] -->|register| Registry Registry -->|resolver bulunamazsa hata| Message ``` ### 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 * **`ORDER` context'i tamamen ölü.** Bir alıcının **belirli bir siparişi** hakkında mesajlaşabileceği bir yol yok — sadece genel `SUPPORT` hattı 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) ile `PRODUCT` konuşması aynı isimde ama farklı iki şey**, sadece servis çağrısı seviyesinde bağlı: `product-request-buyer.service.ts`, talep oluşunca `PRODUCT` konuşmasına bir sistem mesajı yazıyor (`getOrCreateProductConversation` + `createSystemMessage`) — ama `ProductRequest` şemasında `conversationId` gibi kalıcı bir alan yok. Konuşmayı bulmak için her seferinde alıcı id'siyle yeniden çözümleniyor. * **`Conversation.contextId` bilinçli olarak `string`** (registry deseni döngüsel bağımlılığı önlemek için böyle tasarlanmış) — ama bu da [Sipariş taraf ilişkileri](/v2/siparis-iliskileri)'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-group` mesajlaş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ın `AdminBuyerOfficer` üzerinden atanmış bir yetkilisi varsa o kullanılıyor; yoksa `Math.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/join` herhangi 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: true` ile "içinde olmadığım konuşmaları" listeleyebiliyor, ama bir durum alanı (ör. "atanmadı", "işleniyor", "çözüldü") yok — sıralama sadece `updatedAt`. 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](/v2/sirket-depo-siparis)'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 (`AdminBuyerFeedbackHistory` alı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ı](/v2/alan-haritasi)'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 * `ORDER` context'i için bir resolver eklenmeli (muhtemelen `order` modülünde, `return-conversation.resolver.ts`'e paralel) — ya da enum'dan tamamen kaldırılıp `SUPPORT`'a devredilmeli. İkisinden biri: ölü kod olarak kalmamalı. * `ProductRequest`'e `conversationId` alanı 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ı](/v2/alan-haritasi)'ndaki Satış tablosuyla ve [Sipariş taraf ilişkileri](/v2/siparis-iliskileri)'ndeki gevşek referans temasıyla birlikte ele alınacak. ## Sipariş sürecindeki taraf ilişkileri \[Gerçek ilişki mi, kopya mı, tekil mi?] Sipariş sürecindeki taraflar üç farklı şekilde `BuyerOrder`'a bağlanıyor — hepsi aynı güçte değil: * **Gerçek ilişki (Mongoose `ref`):** sorgulanabilir, `populate` edilebilir. * **Anlık kopya (embedded copy):** o an nasıl göründüğünü saklar; canlı kayda geri dönüş yok. * **Gevşek referans (düz string ID):** iki taraf da aynı ID'yi metin olarak tutar, ama veritabanı seviyesinde bir bağ yok — populate edilemez, sadece uygulama kodu ID'yi elle eşler. ### Taraf taraf durum | Taraf | Order'a bağlanma şekli | Not | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | | Buyer | Anlık kopya (`BuyerCopy`, `buyerAddress`, `buyerInvoiceAddress`) | Sipariş anındaki alıcı/adres bilgisini dondurur — bilinçli tasarım. | | Warehouse | Anlık kopya (`WarehouseCopy`) | Aynı şekilde dondurulmuş. | | Officer | Anlık kopya (`pickerOfficer`, `buyerOfficers`) | Aynı şekilde dondurulmuş. | | Seller | **Yok** — doğrudan bağ yok | Sadece `StockEntry.seller` üzerinden dolaylı (2 sıçrama), otomatik populate edilmiyor. | | Payment | **Gerçek ilişki, tek yönlü** — `purchase.payment: ObjectId ref 'Payment'` | Ters yönde `Payment.orderId` sadece `string`, `ref` tanımlı değil — Payment'tan Order'a populate edilemez. | | Transfer | **Gerçek ilişki** — `transfers[]` ve item bazlı `transfer`, `ref: 'BuyerOrderTransfer'` | İki yönde de sorgulanabilir. | | Stock (yeni) | **Gerçek ilişki** — item bazlı `stockEntryReferences[]` (`ref: 'StockEntry'`), `stockExitReference` (`ref: 'StockExit'`) | Bu zincir zaten `StockEntry.seller`'a kadar uzanıyor — bkz. [Yeni ihtiyaçlar](/v2/yeni-ihtiyaclar). | | Stock (eski) | **Gerçek ilişki** — `stockInReferences[]`, `stockOutReference` | Legacy sistemin paralel kalıntısı. | | Invoice | **Gevşek referans** — Order tarafında sadece düz bir özet (`BuyerOrderInvoice`: documentNo, uuid, tutar); Invoice tarafında `invoiceLineReferences[].referenceId` sadece `string`, `ref` yok | İki yönde de gerçek ilişki yok. | | Financial / Cari | **Gevşek referans** — `AccountTransaction.referenceId` / `referenceType` sadece `string`, `ref` yok, `referenceType` için enum bile tanımlı değil (yorum satırında "ORDER, PAYMENT vs." yazıyor) | En gevşek bağ burada. | | Product (catalog) | Kopya (`productId: number`) | Mongo→MySQL arası olduğundan native `ref` zaten mümkün değil. | ### Sonuç Karışık bir tablo: **Payment, Transfer ve Stock tarafı gerçek Mongoose ilişkileriyle bağlı** — sorgulanabilir, zincirlenebilir. **Invoice ve Financial/Cari tarafı ise gerçekten tekil yaşıyor** — order ile aralarında veritabanı seviyesinde hiçbir bağ yok, sadece iki ayrı koleksiyonda aynı ID'nin metin olarak durmasına güveniliyor. Ayrıca bu iki modül birbirinden habersiz, aynı problemi (gevşek referans) farklı şekilde çözmüş: `invoice` bir `type` enum'u tanımlamış (`InvoiceLineReferenceType.ORDER`), `financial` ise `referenceType` için enum bile tanımlamamış. Bu, [Yeni ihtiyaçlar](/v2/yeni-ihtiyaclar) sayfasındaki "satış-alış izlenebilirliği" ihtiyacının asıl can alıcı noktası: stok zinciri zaten sağlam, ama **fatura ve cari tarafı sipariş sürecinden yapısal olarak kopuk**. ### Açık soru v2'de `Invoice.invoiceLineReferences` ve `AccountTransaction.referenceId/referenceType` alanlarının gerçek Mongoose `ObjectId` + `ref` ilişkilerine çevrilmesi (ya da en azından iki modülün ortak, tutarlı bir "discriminated reference" deseni kullanması) gündeme alınmalı. Bu sayfa sadece satış tarafını (order'ın kendisini) inceliyor. Alış tarafı (satıcıdan giren mal) ve iki yönlü iade için: [Uçtan uca izlenebilirlik](/v2/uctan-uca-izlenebilirlik). ## Şirket, depo, sipariş hiyerarşisi \[Hedef yapının ilk kararı] v2'nin veri hiyerarşisi şöyle kurulacak: **Company → Warehouse → Order.** Kullanıcılar (admin, yetkili, vb.) bu ağacın *içine gömülmüyor* — hangi şirkette veya depoda çalışabileceklerini ayrı bir **çalışma izni** kaydı belirliyor. :::note[Company neden bu isim?] Gerçek anlamı "şube" olan bir gruplama — bugün Haljet tek işletme, ileride birden fazla şube/birim olabilir. Ama isim olarak **"Company"** tercih edildi; kod ve dokümanlarda bu terim kullanılacak. ::: ### Bugün nasıl? Bugünkü şemada bu hiyerarşi örtük ve iki farklı modele dağılmış durumda: | Bugünkü kurgu | Sorun | | ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `Warehouse.adminId` her depoyu **tek bir** `Admin`'e bağlıyor, `onDelete: Cascade` ile — admin silinirse depo da silinir. | Kullanıcı kaydı (kim admin) ile depo sahipliği aynı FK'de birleşmiş. | | `Admin.warehouses` bir admin'in birden fazla depoya sahip olabildiğini gösteriyor. | `Admin` böylece hem "yönetici rolündeki kullanıcı" hem örtük bir "tenant sahibi" gibi davranıyor — iki farklı kavram tek modelde. | | `Permission` / `UserPermission` düz bir yetki listesi: kullanıcı hangi işlemi yapabilir. | "Nerede" (hangi depoda/şirkette) çalışabileceği bilgisini taşımıyor; depo ataması `AdminOfficer` gibi ayrı join tablolarıyla dolaylı yürüyor. | ### Hedefte nasıl? ```mermaid flowchart TB Company[Company] --> Warehouse[Warehouse] Warehouse --> Order[Order] User[Kullanıcı] -. çalışma izni .-> Warehouse Warehouse -. türetilir .-> Company ``` * **Company** yeni bir üst model — bugünkü `Admin.warehouses` ilişkisinin yerini alır. Bir Company birden fazla Warehouse'a sahip olabilir. * **Warehouse**, `adminId` yerine `companyId` taşır. Depo artık bir kullanıcıya değil, bir şirkete bağlı. * **Order**, bugün olduğu gibi Warehouse'a bağlı kalır — bu seviyede değişiklik yok. * **Kullanıcılar** bu ağaca FK ile gömülmüyor. **Karar: çalışma izni her zaman Warehouse seviyesinde** — Company ayrıca atanabilir bir seviye değil. Bir kullanıcının "hangi şirketlerde çalıştığı", atandığı depoların bağlı olduğu şirketlerden **türetilir** (birden fazla depo aynı şirkete bağlıysa, o şirket bir kez görünür). Aynı kullanıcı birden fazla depoda (farklı şirketlere bağlı olsa bile) çalışma izni taşıyabilir. ### Aktif depo bağlamı nasıl taşınır: HTTP header Bir kullanıcının birden fazla depoda çalışma izni olabildiği için, her istekte **hangi depo bağlamında** işlem yaptığı belirlenmeli. Seçim akışı: kullanıcı önce atandığı depoların bağlı olduğu **şirketleri** görür (türetilmiş liste) → bir şirket seçer → o şirketin **depolarını** görür → bir depo seçer. **Karar:** Bu seçim, her endpoint'e ayrı `companyId`/`warehouseId` parametresi olarak eklenmek yerine — tıpkı JWT token'ın zaten öyle taşınması gibi — bir **HTTP header** ile taşınacak (ör. `X-Warehouse-Id`). Sunucu tarafında bu header, mevcut `AtGuard`'a benzer bir guard tarafından okunur; kullanıcının o depoda gerçekten çalışma izni olup olmadığı doğrulanır; controller'lara `@GetCurrentUserId()`'ye benzer bir `@GetWarehouseContext()` decorator'ıyla enjekte edilir. Company, header'daki depodan türetilir — ayrıca taşınmasına gerek yok. Bu, her endpoint imzasına iki ekstra parametre eklemek yerine, kimlik doğrulamayla aynı katmanda çözülen tek bir cross-cutting concern haline getiriyor. ### Kapsam: sadece admin/officer'a özel değil, bütün alanlarda geçerli **Karar:** Çalışma izni admin/officer atamasına özel bir kontrol değil — warehouse'a bağlı veriyi okuyan/yazan **her endpoint, hangi alanda olursa olsun** bu kontrolden geçmeli. Dört alanın hepsinde karşılığı var: | Alan | Warehouse'a bağlı örnek | | -------- | -------------------------------------------------------------------------------------------------------------- | | Admin | Yetkili ataması, alıcı CRM'in destek konuşmalarındaki görünürlüğü (bkz. [Satış alanı detayı](/v2/satis-detay)) | | Satış | `WarehouseProduct` (depoya özel fiyat/stok kartı), depoya göre katalog görünürlüğü | | Lojistik | `stock`, `transfer`, `warehouse`'un kendisi | | Muhasebe | `FinancialAccount.warehouseId`, depo bazlı fatura sırası | Yani `@GetWarehouseContext()` guard'ı, tek bir modüle özgü bir özellik değil — kimlik doğrulama (`AtGuard`) gibi, warehouse'a bağlı veri okuyan/yazan hemen her controller'da kullanılacak **standart bir katman** olarak tasarlanmalı. ### Permission ile ilişkisi İki sistem ayrı kalıyor, birlikte okunuyor: * **Permission / UserPermission** (mevcut, değişmiyor) → kullanıcının **ne** yapabildiğini tanımlar (yetki kodu). * **Çalışma izni** (yeni) → kullanıcının **nerede** (hangi Warehouse'da; Company oradan türetilir) çalışabildiğini tanımlar. Bir işlemin yetkisi kontrol edilirken ikisi birlikte sorgulanır: "bu işlemi yapabiliyor mu" + "bu depoda/şirkette çalışıyor mu." ### Etkilenecek modüller Aşağıdaki liste Company/Warehouse modelinin kendisinden doğrudan etkilenenler — çalışma izninin genel kapsamı için yukarıdaki bölüme bakın, bu tablo kapsayıcı değil. | Modül | Etki | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `warehouse` | `Warehouse.adminId` kalkar, `companyId` gelir. Yeni bir `Company` CRUD yüzeyi gerekir. | | `admin` | `Admin` modelinin "tenant sahibi" anlamı kalkar — sadece yönetici rolündeki kullanıcıyı temsil eder. [Alan haritası](/v2/alan-haritasi)'ndaki "üç ayrı iş bir arada" notunu kısmen çözer. | | `officer` | Depo ataması bugünkü `AdminOfficer` yerine yeni çalışma izni kaydına taşınabilir. | | `financial` | Hesaplar bugün depo bazlı (`FinancialAccount.warehouseId`); şirket bazlı konsolide görünüm ihtiyacı doğabilir — açık soru. | | `invoice` | Fatura sıra numarası (`InvoiceSequence`) bugün hangi seviyede tanımlı, Company eklenince aynı kalıp kalmayacağı netleşmeli. | ### Açık noktalar * Company'nin kendi alanları ne olacak (isim, adres, vergi no, vb.)? * `FinancialAccount` ve `InvoiceSequence` company bazında mı, warehouse bazında mı kalacak? * Bugünkü `Warehouse.adminId` / `Admin.warehouses` verisi Company modeline nasıl göç edecek? * `X-Warehouse-Id` header'ı hiç gönderilmezse (veya kullanıcının o depoda izni yoksa) ne olacak — istek reddedilecek mi, yoksa kullanıcının tek/ilk deposuna mı düşecek? * Web/yönetim paneli tarafında depo seçimi nasıl saklanacak (oturum başına mı, her cihazda ayrı mı)? ### Sıradaki adım Bu karar onaylandıktan sonra Prisma şema taslağı (`Company` modeli, `Warehouse.companyId`, yeni çalışma izni tablosu) ve mevcut veriden geçiş sırası planlanacak. ## Uçtan uca izlenebilirlik \[Alış ve satış aynı güçte bağlanmalı] [Sipariş taraf ilişkileri](/v2/siparis-iliskileri) sadece **satış** tarafını (order'ın kendisini) inceledi. Burada iki yönü birden ele alıyoruz: **alış** (satıcıdan giren mal) ve **satış** (alıcıya giden mal). Hedef: fatura, gider ve iade her iki tarafta da aynı sağlamlıkta bağlanabilsin. ```mermaid flowchart LR Seller[Satıcı] --> PI[PlatformInvoice\nalış faturası] PI -. eksik ref .-> SE[StockEntry] SE --> SX[StockExit] SX --> Order[BuyerOrder] Order --> Inv[Invoice\nsatış faturası] SE -. yok .-> RetP[İade → satıcı] Order --> RetS[BuyerOrderReturn] RetS -. yok .-> SE ``` ### Alış tarafı (satıcıdan giren mal) | Bağlantı | Bugünkü durum | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Satıcı → Stok girişi | Var — `StockEntry.seller` | | Alış faturası → Stok girişi | **Yok** — `PlatformInvoice`'ta sadece `stockProcessed: boolean` bayrağı var; hangi `StockEntry`(ler)'i oluşturduğuna dair gerçek bir referans yok | | Gider → alış | Henüz yok — [Yeni ihtiyaçlar](/v2/yeni-ihtiyaclar)'daki gider kaydı, isteğe bağlı olarak bir `StockEntry`'e/alışa bağlanabilmeli (ör. gümrük, nakliye gideri) | | İade → satıcı | **Yok / ölü kod** — `financial`'da `TransactionType.STOCK_RETURN` ("Satıcıya ürün iadesi") tanımlı ama kodda hiçbir yerde tetiklenmiyor; `stock` modülündeki `StockExitType` (`SALE`, `FIRE`, `ADJUSTMENT`) arasında satıcıya iade diye bir tip yok | ### Satış tarafı (alıcıya giden mal) | Bağlantı | Bugünkü durum | | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Stok çıkışı → Sipariş | Var — `StockExit.buyerOrder`, item bazlı `stockExitReference` | | Satış faturası → Sipariş | Gevşek referans — bkz. [Sipariş taraf ilişkileri](/v2/siparis-iliskileri) | | Gider → satış | Henüz yok — teslimat/kargo gibi sipariş özelinde oluşan bir gider bağlanabilmeli | | İade → Sipariş | Var, sağlam — `BuyerOrderReturn.buyerOrder` (ref), item bazlı `orderProductId` (ref `BuyerOrderProduct`); tamamlanınca `financial-buyer.service.ts` üzerinden `REFUND_BALANCE_FOR_RETURN` ile cari iadesi tetikleniyor | | İade → kaynak stok girişi / satıcı | **Yok** — `ReturnRequestItem` sadece ürünün anlık görüntüsünü (`ReturnRequestProductSnapshot`) tutuyor; geldiği `StockEntry`'e veya satıcıya referans yok. Kusurlu ürün iadesi satıcıya otomatik yansıtılamıyor. | ### Sonuç Satış tarafı (stok çıkışı → sipariş → iade) kendi içinde zaten iyi bağlı. Asıl boşluk **alış tarafında**: alış faturası stoğa bağlanmıyor, satıcıya iade hiç uçtan uca modellenmemiş (dead code + eksik stok çıkış tipi), ve satış iadesi geldiği alışa/satıcıya geri izlenemiyor. Gider de her iki tarafa da — sabit company/warehouse kapsamının yanında — isteğe bağlı olarak bağlanabilmeli. ### Karar: iade bir "tür", ayrı ama referanslı bir kayıt İade, ileri yöndeki hareketin (alış ya da satış) ters kaydı olduğu için kendi başına ilgisiz bir şey değil — **her zaman hangi ileri kaydı tersine çevirdiğini bilen, o türden bir kayıt**. Satış tarafında bu prensip zaten kurulu: `BuyerOrderReturn` ayrı bir koleksiyon ama orijinal `BuyerOrder`'a gerçek bir referansla bağlı (kendi `status`, `history`, medya alanları olduğu için `BuyerOrder`'a tek bir `orderType` alanıyla birleştirilmiyor — **karar: ayrı-ama-referanslı yapı korunuyor**). Alış tarafında da aynı desen kurulmalı: satıcıya iade, `StockExitType`'a yeni bir değer (`RETURN_TO_SELLER`) ya da `StockEntry`'ye gömülü bir `type` alanı olarak değil, `BuyerOrderReturn`'e benzer **ayrı bir model** (ör. `StockEntryReturn`) olarak kurulmalı — orijinal `StockEntry`'e gerçek bir referansla bağlı. Böylece iki taraf da aynı prensibi paylaşır: iade her zaman kendi kaydı, ama hep bir ileri kayda referans veriyor. **Karar:** Bu yeni model basit tutulacak — `BuyerOrderReturn`'deki `status`/`history`/medya deseni burada tekrarlanmayacak. Sadece orijinal `StockEntry`'e referans, miktar ve gerekçe yeterli. ### Açık noktalar * `PlatformInvoice`'a `StockEntry`'e gerçek bir referans eklenmeli. * `ReturnRequestItem`'a kaynak `StockEntry`/satıcı referansı eklenmeli mi (kusurlu ürünü satıcıya bildirebilmek için)? * Giderin alışa/satışa bağlanması her zaman isteğe bağlı mı olacak, yoksa bazı gider kategorileri için zorunlu mu? ### Sıradaki adım Bu bulgular, hedef modül şeması ve Prisma/Mongo şema taslağı planlanırken [Sipariş taraf ilişkileri](/v2/siparis-iliskileri) ve [Yeni ihtiyaçlar](/v2/yeni-ihtiyaclar) ile birlikte ele alınacak. ## Yeni ihtiyaçlar \[Planlama sırasında ortaya çıkanlar] Bu sayfa, v2 planlanırken ortaya çıkan ve mevcut kodda karşılığı olmayan (ya da eksik kalan) ihtiyaçları toplar. Bunlar [Alan haritası](/v2/alan-haritasi)'ndaki mevcut modül sınıflandırmasını etkiler; hedef yapı çizilirken hesaba katılmalı. ### Muhasebe: gider (expense) takibi Bugün `FinancialAccount` / `AccountTransaction` (Mongo) sadece **sipariş, alıcı ve satıcı tedariki eksenli** hareketleri modelliyor. `TransactionType` enum'undaki 20 değerin hepsi bir siparişe, cari bakiyeye veya satıcıdan stok tedarikine bağlı (`STOCK_PURCHASE`, `REFUND_BALANCE_FOR_ORDER`, `REWARD`, vb.). Kira, maaş, fatura gibi **genel işletme gideri** kavramı yok. * **İhtiyaç:** Cari tarafına bir gider/expense kaydı eklenmeli. * **Kapsam:** Karar verildi — gider hem Company hem Warehouse seviyesinde tutulabilmeli. Hangisinin kullanılacağı operasyona göre değişir (bazı giderler tek bir depoya özgüdür — kira, elektrik; bazıları şirket geneline yayılır — merkezi bir hizmet, toplu bir fatura). [Çalışma izni](/v2/sirket-depo-siparis) için kurulan aynı kapsam deseni (Company **veya** Warehouse'a bağlanabilen, ikisi birlikte zorunlu olmayan alan) burada da kullanılabilir. * **Rol kısıtı:** Gider ekleme/görme gibi işlemler sadece belirli rollere açık olmalı — mevcut `Permission` sistemi ("ne yapabilir") ile [çalışma izni](/v2/sirket-depo-siparis) ("hangi company/warehouse'da") birlikte bunu sağlayabilir. * **Kategori yönetimi:** Karar verildi — gider kategorileri sabit bir enum değil, admin tarafından eklenip düzenlenebilen dinamik bir tablo olacak (bugünkü `PriceSource`, `CompanyType` gibi admin-CRUD modellerine benzer). Kurulumda önceden tanımlı (predefined) kategorilerle seed edilecek; admin sonradan yenilerini ekleyebilecek. Açık sorular: * Mevcut `AccountTransaction` koleksiyonuna yeni bir `TransactionType` olarak mı eklenecek, yoksa ayrı bir model mi olacak? * `report` modülündeki finansal raporlara (`FinancialAccountReport`) nasıl yansıyacak — Company ve Warehouse bazlı giderler tek bir toplam raporda nasıl birleştirilecek? ### Satış-alış arası izlenebilirlik (ürün yolculuğu) Bugün `stock` modülünde FIFO zinciri veri seviyesinde zaten bağlı: * `StockEntry.seller` → ürün hangi satıcıdan geldi * `StockExit.stockEntryReferences[]` → çıkış hangi giriş lot(lar)ından tüketildi (FIFO) * `StockExit.buyerOrder` → çıkış hangi siparişe gitti Yani "bu ürün şu satıcıdan geldi, şu siparişe gitti" zinciri veride kurulu, ama bunu uçtan uca gösteren **keşfedilebilir bir görünüm/uç nokta yok**. Bugün bu iz sürme resmi olarak HKS'ye (dış sistem) bildiriliyor; iç sistemde aynı düzeyde bir izlenebilirlik sağlanmıyor. Asıl can alıcı nokta stok zincirinde değil — orası zaten sağlam. Sipariş sürecindeki **tüm** tarafların (fatura, cari dahil) order'a ne kadar sağlam bağlı olduğunun tam dökümü için: [Sipariş sürecindeki taraf ilişkileri](/v2/siparis-iliskileri). Alış tarafının (satıcıdan giren mal) ve iki yönlü iadenin aynı incelemesi için: [Uçtan uca izlenebilirlik](/v2/uctan-uca-izlenebilirlik). * **İhtiyaç:** "Bu ürün nereden geldi, nereye gitti" sorusuna iç sistemden de cevap verebilen bir görünüm — muhtemelen `report` ya da `stock` altında yeni bir "ürün yolculuğu" uç noktası. Açık sorular: * Bu görünüm tekil ürün/parti (lot) seviyesinde mi, yoksa toplu rapor seviyesinde mi olacak? * Hangi roller görebilecek? * HKS'nin zaten sağladığı resmi izlenebilirlikle iç sistemin ilişkisi ne olacak — aynı veriyi tekrar mı üretecek, yoksa onu tamamlayan bir iç görünüm mü olacak? ### Sıradaki adım Bu iki ihtiyaç, [Alan haritası](/v2/alan-haritasi)'ndaki muhasebe ve satış/lojistik alanlarının sınırlarını etkiliyor; hedef modül şeması çizilirken ayrıca ele alınacak. ## Ticaret \[Üründen sipariş belgesine] Bu grup, alıcının gördüğü vitrin ile sipariş belgesinin kurulmasını kapsar. Siparişin **yaşam döngüsü** [order](/structures/commerce#order-modülü-nerede) modülündedir; bu sayfa vitrin ve sepet tarafıdır. ### `catalog` **Görevi:** Ürün gerçeği. İsim, KDV, birim, kategori, görsel, HKS kodu, depo fiyatı ve arama. | Yol | Kimin için | | --------------------------------------- | --------------------------------- | | `catalog/public`, `catalog/third-party` | Açık | | `catalog/buyer` | Alıcı | | `catalog/officer` | Yetkili | | `catalog/admin` | Yönetici (birim/KDV için ek izin) | Alıcı listesi şu sırayı izler: alıcının seçili adresi → depo kararı → MeiliSearch filtresi (depo, şirket tipi, kategori) → depo fiyatlarıyla zenginleştirme. Sonuç yoksa BigQuery’ye “bulunamadı” olayı yazılır. Ürün kaydı veya silinmesi `product.upsert` / `product.deleted` olaylarıyla arama indeksini günceller. Saatlik cron indeksi baştan kurar (üretimde). Alıcı, katalogda olmayan ürün için **ürün talebi** açabilir. Bu talep Mongo `productRequests` koleksiyonundadır; durum `PENDING` veya `REVIEWED`. Şema: [Katalog ve stok kartı](/data/prisma/catalog). ### `basket` **Görevi:** Alıcının henüz sipariş olmamış satırları. Yol: `basket/buyer`. Satırlar Prisma `ProductBasket` tablosundadır (kullanıcı + ürün, miktar, aktiflik). Sepet, satın alma önizlemesinde depo fiyatı ve asgari tutarla birleştirilir. ### `purchase` **Görevi:** Sepeti **sipariş belgesine** çevirmek; henüz yaşam döngüsünü yürütmez. | Yol | Kimin için | | ------------------ | --------------------- | | `purchase/buyer` | Alıcı | | `purchase/officer` | Yetkili (alıcı adına) | Önizleme: adres ve fatura adresi doğrulanır, depo seçilir, cari okunur, kargo / içeride taşıma / bakiye kullanımı hesaplanır, teslimat bloğu kurulur. Oluşturma: kullanıcı kimliğine MurLock konur; ödeme bekleyen eski siparişler iptal edilebilir; `OrderBuyerService.createOrder` çağrılır. Ödeme yöntemine göre ilk sipariş durumu değişir — [Alışveriş akışı](/flows/shopping). Sabitler kodda: ücretsiz kargo eşiği **3000**, içeride teslim hizmet bedeli **250** (para birimi `TRY`). ### `post` **Görevi:** Uygulama içi içerik. Prisma `Post`. Tipler: `SLIDER`, `BANNER`, `STORY`, `ACADEMY`. Hedef kitle `userType` alanıdır. Alıcı listesi `post/buyer` yolunda herkese açıktır. Satıcı, yetkili ve yönetici uçları rollüdür. Bu, satıcı teklifi değildir; vitrin / akademi içeriğidir. ### `procurement` **Görevi:** Satıcının “mal tedarik etmek istiyorum” talebi. Yol: `procurement/seller`. Kayıt Mongo `procurementRequests` koleksiyonuna gider; satıcı ve ilçe gömülü kopyadır. Görseller dosya deposuna yüklenir. Durumlar: `PENDING`, `APPROVED`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`. ### `static` **Görevi:** Politika metinleri (`static/policy`, açık) ve alıcıya özel statik içerik (`static/buyer`). ### Sipariş modülü nerede? Sipariş belgesi, durum makinesi, iade ve teslimat **order** + **transfer** + **warehouse** üçlüsündedir: * [Lojistik](/structures/logistics) * [Alışveriş](/flows/shopping) * [Hazırlık ve teslimat](/flows/fulfillment) ## İletişim \[Sohbet, kutu ve yayın] Üç kanal vardır. Karıştırmamak için: | Kanal | Nerede durur | Ne zaman | | ------------------------------- | ---------------------------------- | ----------------- | | Sohbet | Mongo `conversations` / `messages` | İki yönlü konuşma | | Bildirim kutusu | Mongo `notifications` | Tek yönlü kayıt | | Push / SMS / e-posta / Telegram | Dış servis | Anlık uyarı | ### `message` **Görevi:** Uygulama içi konuşma. Konuşmanın bir **bağlamı** olabilir: sipariş, iade, destek, ekip, ürün (`ConversationContextType`). Mesaj tipleri sorun, istek, öneri, duyuru; ilk üçünde durum makinesi vardır (Türkçe sistem cümleleri kodda sabittir). Tepki, düzenleme, silme ve okundu ayrı servislerdir. Olaylar: `message.created`, `updated`, `deleted`, `reacted`. Dinleyiciler Firebase anlık kanalına ve bildirime yazar. Yapay zeka yanıtı Bull kuyruğu `haljet-ai` ile Gemini’ye gider. ### `notification` **Görevi:** Yönetici yayını ve kutu kaydı. Yol `notification`, yönetici. İsteğe bağlı alıcı segmenti çözülür, cihaz jetonları parçalar halinde FCM’e gönderilir, aynı metin kutuya yazılır. Sipariş ve görev bildirimleri bu modülü **dolaylı** kullanır (`OrderNotifierService`, `WorkflowNotifierService`): hem push hem kutu. Cron 10:00 / 17:00 kodda kapalıdır. ### `post` Vitrin içeriği [Ticaret](/structures/commerce) altındadır. Alıcıya açık liste `post/buyer` yolundadır. ### Sipariş yaşam döngüsü bildirimleri Sipariş durumu değişince `OrderNotifierService` devreye girer: * `PENDING` — yöneticiye e-posta * Onay, hazırlık, hazır, sevk, teslim, iptal, ödeme zaman aşımı — alıcıya push + kutu Yeni kayıtta Telegram + pazarlama yetkililerine push vardır. Detay: [Bildirimler](/flows/notifications). ## Bağımlılıklar \[Yapılar nasıl birbirine bağlanır] Modüller tek başına durmaz. Sipariş, ödeme ve depoyu aynı anda ilgilendirir. Bu sayfa **modül import’ları**, **olaylar** ve **kuyruklar** üzerinden gerçek bağları gösterir. ### Ana omurga Alışveriş omurgası şöyledir. Ok yönü “bunu kullanır / buna yazar” anlamındadır. ```mermaid flowchart TB Basket[basket] --> Purchase[purchase] Purchase --> Order[order] Catalog[catalog] --> Basket Catalog --> Purchase Order --> Payment[payment] Order --> Financial[financial] Order --> Transfer[transfer] Order --> Warehouse[warehouse] Order --> Stock[stock] Order --> Invoice[invoice] Order --> Notification[notification] Order --> Report[report] Transfer --> Order Warehouse --> Financial Invoice --> Izibiz[izibiz] Order --> Hks[hks] ``` * **catalog** fiyat ve ürünü sağlar; sepet ve satın alma bunu okur. * **purchase** sipariş belgesini kurar; **order** saklar ve yaşam döngüsünü yürütür. * **payment** kart sonucunu order’a bildirir. * **financial** bakiye ve defteri günceller. * **transfer** ve **warehouse / stock** teslimat ve stok hareketini yürütür. * **invoice**, **hks**, **notification**, **report** siparişin yan etkileridir. ### Kimlik çevresi ```mermaid flowchart LR Auth[auth] --> User[user] Auth --> Buyer[buyer] Auth --> Firebase[firebase] Auth --> Financial[financial] Buyer --> Warehouse[warehouse] Buyer --> Izibiz[izibiz] Admin[admin] --> Buyer Admin --> Order[order] Officer[officer] --> Order Officer --> Transfer[transfer] Officer --> Message[message] ``` Yeni alıcı kaydı `auth` içinde `User` + `Buyer` + `AdminBuyer` üretir, `buyer.firestore-sync` olayını yollar ve `FinancialModule` üzerinden kayıt ödülünü dener. Yönetici ve yetkili alıcı işlemleri Firestore olayını tekrar kullanır. ### Olay ağı İç olaylar `@nestjs/event-emitter` ile gider. Aşağıdaki tablo koddaki emit / listen çiftleridir. | Olay | Kim üretir | Kim dinler | Sonuç | | ------------------------------------ | ---------------------------------------------- | ---------------------- | ----------------------------------------------------------- | | `buyer-order.created` | Sipariş servisi (ödeme tamam veya cari/kapıda) | Sipariş dinleyicisi | Bildirim, BigQuery, CRM sayacı, rapor kuyruğu, bölge kilidi | | `buyer-order.changed` | Sipariş durum değişimi | Sipariş dinleyicisi | Bildirim, mali fark, rapor yenileme | | `buyer-order-product.changed` | Kalem değişimi | Sipariş dinleyicisi | Kalem yan etkileri | | `payment.updated` | Ödeme servisi | Ödeme dinleyicisi | Siparişi ödenmiş veya başarısız işaretler | | `product.upsert` / `product.deleted` | Katalog yönetici servisi | Katalog dinleyicileri | MeiliSearch indeks güncelleme | | `buyer.firestore-sync` | Kayıt, CRM, sipariş | Alıcı dinleyicisi | Firestore | | `message.*` | Mesaj servisleri | Mesaj dinleyicileri | Anlık kanal ve bildirim | | `task.*` | Görev servisi | İş akışı dinleyicileri | Görev bildirimi | | `transfer.updated` | Transfer servisi | Transfer dinleyicisi | Teslimat yan etkileri | | `officer-location.changed` | Yetkili servisi | Konum dinleyicisi | Konum yayını | | `product-sale.recorded` | Sipariş oluşunca | Rapor dinleyicisi | `report` kuyruğu | :::note[Kayıtlı ama üretilmeyen olaylar] `stock-in.created` ve `stock-out.created` için dinleyici vardır; mevcut kaynakta emit bulunamadı. `warehouse-product-stock` kuyruğunun işleyicisi yoktur. Bu, “ileride bağlanacak / eski iskelet” olarak okunmalıdır; aktif stok akışı doğrudan servis çağrılarıyla yürür. ::: ### Kim kimi import eder (özet) Nest `imports` dizisinden sadeleştirilmiş tablo: | Modül | Doğrudan bağlandığı iş modülleri | | ----------- | ----------------------------------------------------------------------------------------------------------------------------- | | `order` | buyer, warehouse, stock, payment, transfer, notification, financial, officer, izibiz, hks, invoice, report, message, bigquery | | `purchase` | buyer, order, catalog, warehouse | | `basket` | purchase, catalog, order, bigquery | | `catalog` | hks, bigquery, message, officer | | `admin` | user, auth, order, purchase, report, warehouse, buyer | | `officer` | transfer, admin, order, message, financial, invoice | | `auth` | user, financial, bigquery | | `buyer` | izibiz, warehouse, bigquery | | `financial` | payment, message | | `invoice` | izibiz, financial, seller | | `transfer` | officer, order, warehouse, stock, financial | | `message` | notification, order, officer | | `warehouse` | user, order, hks, seller, financial | | `report` | (sipariş / stok / cari belgelerini okur; satış olayı kuyruğu) | ### Okuma rehberi * “Sipariş oluşunca ne olur?” → [Alışveriş](/flows/shopping) ve [Bildirimler](/flows/notifications) * “Para nerede hareket eder?” → [Ödeme](/flows/payment) ve [Para ve fatura](/structures/money) * “Depo stoğu nasıl düşer?” → [Hazırlık ve teslimat](/flows/fulfillment) ## Kimlik ve erişim \[Hesap, oturum ve yer] Bu grup, “kim bu kişi ve nerede?” sorusunu cevaplar. Sipariş ve ödeme bu temelin üstüne kurulur. ### `auth` **Görevi:** Hesap açmak, doğrulamak, jeton vermek ve oturumu kapatmak. Denetleyici yolu `auth`. Sınıf düzeyinde API anahtarı bekçisi vardır. Kayıt ve giriş uçları herkese açıktır; çıkış kimliği doğrulanmış kullanıcı içindir. | Servis | İş | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Giriş | Telefon, Firebase kimliği veya parola. Jeton üretir, yenileme özetini kullanıcıya yazar. | | Kayıt | Alıcı, satıcı, yetkili, yönetici tipleriyle. Alıcı kaydında Telegram uyarısı, pazarlama yetkililerine push, `AdminBuyer` bağlantısı, Firestore senkron olayı, aktifse kayıt ödülü (`financial`), BigQuery kayıt olayı vardır. | | Telefon / e-posta | Kod üretir ve doğrular. Kodlar Prisma `PhoneVerification` / `EmailVerification` tablolarındadır. | Şema: [Kimlik ve izinler](/data/prisma/identity). Akış: [Kayıt ve giriş](/flows/registration). ### `user` **Görevi:** Hesabın kendisi — ad, iletişim, parola, avatar, cihaz, hata logu. | Yol | Erişim | | ------------- | ------------------------------------ | | `user` | Kimliği doğrulanmış herhangi bir tip | | `user/device` | FCM cihaz kaydı | | `user/log` | İstemci logu (Mongo `userLogs`) | Cihaz jetonu hem Prisma `UserDevice` tablosuna yazılır hem de sipariş belgelerindeki kullanıcı kopyasına gömülür; böylece push, sipariş anındaki jetonlarla da gönderilebilir. ### `area` **Görevi:** Adres hiyerarşisi. Ülke → il → ilçe → mahalle. Uç `area` herkese açıktır. HKS entegrasyonu için ülke, il, ilçe ve mahallede isteğe bağlı `hksCode` vardır. Adresler bu hiyerarşiye bağlanır. Detay: [Coğrafya ve adres](/data/prisma/geography). ### Bağlı yapılar Kimlik tek başına durmaz: * Alıcı, satıcı, yetkili, yönetici **profil tabloları** kullanıcıya 1:1 bağlanır → [Kişiler ve CRM](/structures/people) * İzin kodları `Permission` / `UserPermission` → [Roller ve yetkiler](/overview/roles) * Alıcı adresi hem kimlik hem teslimat hem fatura içindir → [Alışveriş](/flows/shopping) * Yeni alıcı kaydı cari ödül yazabilir → [Kayıt ödülü](/flows/registration#kayıt-ödülü) ## Modül haritası \[Her yapının görevi] API, `src/modules` altında **domain modülleri** ve `src` kökünde **altyapı modülleri** olarak ayrılır. Aşağıdaki görevler ilgili `*Module`, denetleyici ve servis dosyalarından çıkarılmıştır. ### Nasıl okunur? Her satır “bu ekip / bu ekran ne işe yarar?” sorusuna iş dilinde cevap verir. Teknik bağlantılar [Bağımlılıklar](/structures/dependencies) sayfasındadır. ### Kimlik, kişi ve yer | Modül | Görevi | | ------------- | ----------------------------------------------------------------- | | `auth` | Kayıt, giriş, çıkış, telefon ve e-posta doğrulama, jeton üretimi. | | `user` | Profil, parola, avatar, cihaz (FCM), istemci logları. | | `area` | Ülke, il, ilçe, mahalle. Açık uç. | | `buyer` | Alıcı profili, adres, depo eşlemesi, ekstre, Firestore senkronu. | | `seller` | Satıcı profili, vergi bilgisi, İzibiz bağlantısı. | | `officer` | Yetkili profili, konum, alıcı adına işlem, mesaj. | | `admin` | Yönetici paneli: alıcı CRM, yetkili atama, ana sayfa. | | `buyer-group` | Alıcı segmenti (ciro, sipariş adedi, sepet ortalaması). | Detay: [Kimlik ve erişim](/structures/identity), [Kişiler ve CRM](/structures/people). ### Ticaret | Modül | Görevi | | ------------- | --------------------------------------------------------------------------------- | | `catalog` | Ürün, kategori, arama, ürün talebi, HKS ürün kodu, şirket tipine göre görünürlük. | | `basket` | Alıcı sepeti (MySQL satırları). | | `purchase` | Sipariş önizleme ve oluşturma: teslimat, ödeme kırılımı, asgari sepet. | | `post` | Slider, banner, hikâye, akademi içerikleri. | | `procurement` | Satıcının tedarik talebi (Mongo belge). | | `static` | Politika sayfaları ve alıcıya özel statik içerik. | Detay: [Ticaret](/structures/commerce). ### Sipariş, depo, para | Modül | Görevi | | ----------- | ---------------------------------------------------------------------------- | | `order` | Alıcı siparişi yaşam döngüsü, iade, sorun, anket, heatmap, fatura tetikleme. | | `warehouse` | Depo tanımı, stok, istatistik, heatmap, kapsama alanı, fiyat geçmişi. | | `stock` | FIFO stok girişi / çıkışı (yeni stok modülü). | | `transfer` | Sipariş teslimatı ve araç seferi. | | `payment` | PayTR, Paywall, MagicPay ve manuel tahsilat. | | `financial` | Cari bakiye, hareket defteri, kayıt ödülü tanımları. | | `invoice` | Giden ve gelen e-fatura kayıtları. | Detay: [Lojistik](/structures/logistics), [Para ve fatura](/structures/money). ### İletişim, operasyon, zeka | Modül | Görevi | | ----------------- | -------------------------------------------------------------------- | | `message` | Sohbet, tepki, okundu, bağlama göre konuşma (sipariş, iade, ürün…). | | `notification` | Yönetici yayını, segment, kutu kaydı. | | `workflow` | Depo bazlı kanban: departman, kart, görev, not. | | `report` | Satış, alım, alıcı yaşam döngüsü, cari, pazarlama, BigQuery aktarım. | | `ai` | Açık uç: doğal dil sorgu ve şema bağlamı. | | `price-analytics` | Fiyat mumu, İBB Hal verisi, ürün eşlemesi, ticker. | Detay: [İletişim](/structures/communication), [Operasyon](/structures/operations), [Zeka ve analitik](/structures/intelligence). ### Altyapı klasörleri (modül değil ama yapı) Bunlar `app.module` içinde bağlanır; iş kuralı taşımaz, servis sağlar. | Klasör | Görevi | | ---------------- | ---------------------------------------------------------------- | | `prisma` | MySQL istemcisi | | `common` | Sayfalama, depolama, telefon, tarih, Telegram uyarı, Google Maps | | `firebase` | Push, Firestore, Storage | | `mail` / `sms` | E-posta / SMS | | `meilisearch` | Arama istemcisi | | `izibiz` / `hks` | Fatura ve hal bildirimi | | `gemini` | Metin üretimi | | `bigquery` | Analitik yazımı | ### HTTP yüzeyi Tüm yollar `api` önekinin altındadır. Örnek: alıcı sepeti `api/basket/buyer`. Rol dağılımı [Roller ve yetkiler](/overview/roles) sayfasındadır. ## Zeka ve analitik \[Soru, fiyat ve olay] Üç ayrı “zeka” vardır; birbirinin yerine geçmez. ### `ai` **Görevi:** Herkese açık `ai` ucu. Swagger belgesi uygulama açılışında bu servise verilir; doğal dil sorular bu bağlama göre yanıtlanır. Şema anlatıcısı da aynı belgeden beslenir. Gemini metin üretir, BigQuery sorguları bağlanabilir. Bu, sipariş notu çıkarımı veya sohbet kuyruğundaki AI ile **aynı uç değildir**. Onlar `order` ve `message` içindedir. ### `price-analytics` **Görevi:** Fiyatın zaman içindeki görünümü. | Yol | Kim | | -------------------------------- | --------------------------------------------- | | `price-analytics/public` | Açık grafikler | | `price-analytics/admin` | Yönetici | | `price-analytics/admin/sources` | Dış kaynak tanımı (`PriceSource`) | | `price-analytics/admin/mappings` | Dış isim → iç ürün (`ExternalProductMapping`) | İç mumlar depo fiyat geçmişinden, dış mumlar örneğin **İBB Hal** çekicisinden üretilir. Ham örnek `externalPriceRawSample`, mum `productPriceCandle` koleksiyonlarındadır. Ürün üzerindeki `ProductTickerStats` son fiyat, değişim ve oynaklık özetidir. Cron: saatlik iç/dış mum; iç mum gece yarısı da. ### BigQuery Modül klasörü `src/bigquery`. Rapor ekranı değildir; **olay yazma** katmanıdır. Yazılan tablolar kod enum’undan: siparişler, sipariş kalemleri, alıcı adresleri, fiyat değişimi, arama bulundu/bulunamadı, ürün görüntüleme, alıcı kaydı, ürün talebi. Kim yazar: kayıt, sipariş oluşumu, katalog arama, adres kaydı, fiyat değişimi. Toplu geri yükleme `report/bigquery-migration` ucundadır. Şema: [BigQuery](/data/bigquery). ## Lojistik \[Depo, stok ve teslimat] Alıcı siparişi bir **depoya** düşer. Yetkililer hazırlar, stoğu düşer, kurye veya müşteri teslimi ile kapatır. Bu sayfa o operasyonun yapılarını anlatır. ### `warehouse` **Görevi:** Depo tanımı ve depo içi operasyon. | Yol | İş | | -------------------------- | ------------------------------------------------------------ | | `warehouse/admin` | Depo, hizmet alanı, poligon bölge, araç, ayar, yetkili atama | | `warehouse/officer` | Yetkili depo görünümü | | `warehouse/stock` | Stok giriş/çıkış (eski koleksiyonlar dahil) | | `warehouse/:id/statistics` | Toplu istatistik | | `warehouse/heatmap` | Coğrafi yoğunluk | Prisma tarafında depo, dikdörtgen **hizmet alanı**, poligon **koordinat bölgesi**, gün bazlı asgari sepet, araç ve anahtar-değer ayar tutulur. Stok **miktarı** `WarehouseProduct.stock` alanındadır; hareketin ayrıntısı Mongo’dadır. İki stok dünyası vardır: | Sistem | Koleksiyon | Ne zaman | | --------- | ------------------------------------------------------ | -------------------------------------------------------- | | Eski | `warehouseProductStockIn` / `warehouseProductStockOut` | Manuel giriş, HKS ham veri, yönetici/yetkili stok ekranı | | Yeni FIFO | `stockEntries` / `stockExits` | Sipariş sevkında `StockService` | Şema: [Depo ve teslimat alanı](/data/prisma/warehouse), [Stok ve transfer](/data/mongodb/stock-transfers). ### `stock` **Görevi:** FIFO lot. Giriş lotu (`StockEntry`) kalan miktar taşır; çıkış (`StockExit`) lotlara referans verir. Yol: `stock` — yönetici ve yetkili. Sipariş sevkı bu modülü çağırır: önce uygun lotlar seçilir, sonra satış çıkışı yazılır, sipariş kalemine referans işlenir. Giriş durumları: `PRE_DECLARED`, `DECLARED`, `CONFIRMED`, `CANCELLED`. Çıkış tipi: `SALE`, `FIRE`, `ADJUSTMENT`. ### `order` **Görevi:** Alıcı siparişinin tek belgesi ve durum makinesi. Sipariş **Mongo `buyerOrders`** koleksiyonundadır; MySQL’de sipariş tablosu yoktur. Belge alıcı kopyası, kalemler, ödeme bloğu, teslimat, depo, geçmiş, fatura özeti ve transfer referanslarını bir arada tutar. | Yol | Kimin için | | --------------------------------------- | ------------------------------- | | `order/buyer` | Alıcı (iki ödeme test ucu açık) | | `order/buyer/return` | Alıcı iade talebi | | `order/officer`, `order/officer/return` | Yetkili | | `order/admin`, `order/admin/return` | Yönetici | | `order/heatmap` | Yönetici ve yetkili | Sipariş düzeyindeki durumlar ve kalem düzeyindeki iade alt durumları [durum değerleri](/data/mongodb/enums) sayfasındadır. Akış: [Alışveriş](/flows/shopping), [Hazırlık ve teslimat](/flows/fulfillment). İlgili belgeler: iade (`buyerOrderReturns`), sorun (`buyerOrderIssues`), anket (`orderSurveyResponses`), heatmap (`orderHeatmaps`). ### `transfer` **Görevi:** Siparişi kapıya götürmek. Kurye teslimatlı siparişlerde `BuyerOrderTransfer` açılır. Birden fazla transfer bir **araç seferine** (`WarehouseVehicleTransfer`) bağlanabilir; GPS noktaları ve kapıda tahsilat bu seferde tutulur. | Yol | Kimin için | | ------------------ | --------------------------------------------- | | `transfer/buyer` | Alıcı | | `transfer/officer` | Yetkili (`officer:buyer-order-transfer:full`) | | `transfer/admin` | Yönetici | Durumlar: `PENDING`, `SHIPPING`, `DELIVERED`, `CANCELLED`, `RETURNED`. Teslim, siparişi `DELIVERED` yapar. Kuyruk `transfer-operations`: sevk ve araç faturası üretimi. ### Teslimat türü Sipariş teslimatı iki tiptir (`DeliveryType`): | Değer | Anlamı | | ---------- | ------------------------------------------------- | | `COURIER` | Platform kuryesi. Transfer kaydı bu tipte açılır. | | `CUSTOMER` | Alıcı kendi alır / kendi organize eder. | Sağlayıcı enum’u şu an yalnız `PLATFORM` değerini taşır. ## Para ve fatura \[Tahsilat, cari ve belge] Siparişin bedeli üç yerde izlenir: **ödeme kaydı**, **cari bakiye**, **fatura**. Bunlar aynı tutarın kopyası değil, farklı sorulara cevap verir. * Ödeme: “Kart / havale bu sipariş için geçti mi?” * Cari: “Bu kullanıcının bu depodaki bakiyesi nedir?” * Fatura: “Yasal belge kesildi mi?” ### `payment` **Görevi:** Ödeme sağlayıcıları ve Mongo `payments` belgesi. Yollar herkese açıktır (sağlayıcı geri bildirimi): `payment`, `payment/magicpay`, `payment/paytr`, `payment/paywall`. Sipariş üzerindeki ödeme bloğu (`purchase`) sipariş belgesinin içindedir. `payments` koleksiyonu sağlayıcı işleminin kendisidir: platform, tutar, durum, işlem no, sipariş id. Başarılı veya başarısız güncelleme `payment.updated` olayını üretir; dinleyici siparişi ödenmiş veya başarısız yapar. Akış: [Ödeme](/flows/payment). ### `financial` **Görevi:** Cari. | Yol | Erişim | | ------------------- | --------------------------------------- | | `financial/user` | Kimliği doğrulanmış (depo erişimi olan) | | `financial/admin` | Yönetici | | `financial/officer` | Yetkili | **Bakiye** Prisma `FinancialAccount` tablosundadır: kullanıcı + isteğe bağlı depo, `balance`, `creditLimit`, kasa (`boxBalance`) ve palet (`palletBalance`) sayaçları. Pozitif bakiye alacak, negatif borç anlamına gelir (şema yorumu). **Hareket** Mongo `accountTransactions` koleksiyonundadır: tutar, işlem sonrası bakiye, tip, referans, vade, onay durumu. Tip listesi ve Türkçe etiketler [Cari ve fatura](/data/mongodb/finance-invoices) sayfasındadır. Sipariş, iade, kapı tahsilatı ve stok alımı sistem tiplerini otomatik üretir. Yeni alıcı kaydında aktif tanım varsa `REWARD` da otomatik yazılır. Elle girilebilen çekirdek tipler kodda ayrı listedir (transfer, ödül, telafi, düşüm); ödül hem elle hem kayıt akışında kullanılabilir. ### Kayıt ödülü tanımı Ödül kartı Prisma tablosu değildir. `RewardDefinition` alanları kod listesindedir: `id`, `code`, `name`, `amount`, `warehouseId`, `startDate`, `endDate`, `isActive`. Aktiflik: aynı kod, `isActive`, başlangıç geçmişte, bitiş boş veya gelecekte. Alıcı kaydı `FinancialBuyerService.grantSignupReward` çağırır. Akış ve güncel tanım: [Kayıt ödülü](/flows/registration#kayıt-ödülü). ### `invoice` **Görevi:** Kesilmiş veya gelen e-belge kaydı. | Yol | Niyet edilen rol | | ---------------------------------- | ------------------------------------------------ | | `invoice/buyer` | Alıcı (rol bekçisi var) | | `invoice/admin`, `invoice/officer` | Yönetici / yetkili (etiket var, rol bekçisi yok) | Giden fatura `invoices`, gelen tedarikçi belgesi `platformInvoices`. Sağlayıcı enum’u yalnız `IZIBIZ`. Belge tipi: e-fatura, e-arşiv, makbuz. Numara üretimi Prisma `InvoiceSequence` (tip + önek + yıl). Sipariş belgesine gömülen `invoice` özeti, yasal belgenin kısa kopyasıdır. Asıl UBL / sağlayıcı yanıtı fatura koleksiyonundadır. Akış: [Fatura ve HKS](/flows/invoicing). ### Siparişteki ödeme kırılımı Satın alma, sipariş belgesine `purchase` nesnesini yazar. Burada yöntem (`CASH`, `CARD`, `TRANSFER`, `CHECK`, `ACCOUNT`), çevrimiçi/çevrimdışı tipi, satır kalemleri, kargo, taksit, cari kullanımı ve net toplam durur. Kapıda tahsilat transfer belgesindeki `collectedPayments` ile de izlenir. ## Operasyon \[İç iş, rapor ve tedarik talebi] Günlük saha işinin bir kısmı sipariş ekranında, bir kısmı **görev tahtasında**, bir kısmı **raporlarda** durur. ### `workflow` **Görevi:** Depo bazlı kanban. Yapı tek Mongo belgesinde iç içedir: `Department` (depo) → `Card` (sütun) → `Task` (iş) → not ve geçmiş. Görseller dosya deposuna gider. Atanan kullanıcılara Firebase + kutu bildirimi gider. Yollar: `workflow/department`, `workflow/card`, `workflow/task`, `workflow/user`. Rol etiketi yönetici/yetkili; rol bekçisi bağlı değildir. Olaylar: `task.created`, `task.updated`, `task.note-added`. ### `report` **Görevi:** Operasyon ve yönetim özetleri. Canlı sipariş belgesini her seferinde taramak yerine **önceden toplanmış** Mongo raporları sunar. | Yol | İçerik | Kim | | --------------------------- | ------------------------------- | ----------------- | | `report/product-sales` | Ürün satış gün özeti | Yönetici, yetkili | | `report/product-purchase` | Alım / maliyet özeti | Yönetici, yetkili | | `report/buyer` | Alıcı aktivitesi | Yönetici, yetkili | | `report/buyer-lifecycle` | Yaşam döngüsü ve ödeme kırılımı | Yönetici, yetkili | | `report/financial-account` | Cari özeti | Yönetici, yetkili | | `report/marketing` | Pazarlama | Yalnız yönetici | | `report/bigquery-migration` | Eski veriyi BigQuery’ye aktarma | Yönetici, yetkili | Satış raporu `product-sale.recorded` olayı ve sipariş durum değişimiyle yeniden kurulur. Depo istatistiği ayrı `warehouseReports` koleksiyonu ve `warehouse-report` kuyruğudur. Akış: [Raporlama](/flows/reporting). ### `procurement` Satıcı tedarik talebi [Ticaret](/structures/commerce) sayfasındadır. Operasyon tarafı, talebin onay / işleme / tamamlandı durumlarından geçmesidir. ### `admin` panosu Alıcı panosu (`admin/buyer/board`) CRM’in operasyon yüzüdür: aranacaklar, sipariş bekleyenler, kayıp riski. SSE ile canlı akış jetonla açılabilir. [Kişiler ve CRM](/structures/people). ## Kişiler ve CRM \[Kim, hangi depo, hangi ilişki] Kullanıcı tipi [Roller](/overview/roles) sayfasındadır. Bu sayfa **iş ilişkisi** tarafını anlatır: alıcı hangi yöneticiye bağlı, yetkili hangi depoya bakıyor, alıcı hangi segmente düşüyor. ### `buyer` **Görevi:** Alıcı işletme profili ve adresleri. | Yol | İş | | ----------------- | ------------------------------------ | | `buyer` | Profil; `company-types` herkese açık | | `buyer/address` | Teslimat ve fatura adresleri | | `buyer/warehouse` | Alıcı / yönetici depo görünümü | Seçili teslimat ve fatura adresi alıcı kaydında 1:1 tutulur. Adres, depo hizmet alanına veya poligon bölgeye bağlanır; asgari sepet hem adreste hem bölgede olabilir. Fatura için vergi no, vergi dairesi, TCKN, doğum tarihi, e-fatura ve MERNİS yedek bayrakları adrestedir. Günlük 08:00 cron’u alıcı bakımı içindir. Firestore senkronu olayladır. Yeni alıcı kaydı, aktif tanıma göre cari ödül yazabilir: [Kayıt ödülü](/flows/registration#kayıt-ödülü). ### `admin` **Görevi:** Yönetici işi — özellikle alıcı CRM. `AdminBuyer` kaydı yönetici ile alıcıyı eşler: sipariş sayıları, teslim/iade/sorun özetleri, son arama, durum (`ACTIVE` / `INACTIVE` / `ZOMBIE`), aksiyon durumu, kayıp riski, geri bildirim skoru. Notlar tiplidir (fiyat, teslimat, fatura…). Yetkililer bu kayda atanır. | Yol | İş | | ------------------- | ---------------------------- | | `admin` | Yönetici genel | | `admin/buyer` | CRM (`admin:buyer:full`) | | `admin/buyer/board` | Pano; SSE akışı jetonla açık | | `admin/officer` | Yetkili yönetimi | Gece yarısı `AdminCronService` çalışır. ### `officer` **Görevi:** Saha ve depo personeli. Konum güncellenince `officer-location.changed` yayılır. `officer/buyer` ile yetkili alıcı adına işlem yapar. Depo ataması `AdminOfficer`, alıcı ataması `AdminBuyerOfficer`. ### `seller` **Görevi:** Tedarikçi kartı. Kullanıcı bağlantısı isteğe bağlıdır (kullanıcısız satıcı kaydı olabilir). Ödeme günü `PaymentPeriod` (haftanın günü). Stok girişi ve İzibiz vergi sorgusu bu kartı kullanır. ### `buyer-group` **Görevi:** Alıcıyı ciro, sipariş adedi ve ortalama sepet eşiğine göre kademelendirmek. Grup tanımı Prisma’dadır. `rank` yüksek olan üst kademedir; üç eşik de sağlanmalıdır (şema yorumu). Gece yarısı cron ölçer, `BuyerGroupEvaluation` satırı yazar, gerekirse `Buyer.currentGroupId` değiştirir. Değerlendirme için sipariş geçmişi Mongo’dan okunur. | Yol | Kimin için | | --------------------- | ---------- | | `buyer-group/admin` | Yönetici | | `buyer-group/officer` | Yetkili | | `buyer-group/buyer` | Alıcı | Şema: [CRM ve alıcı grupları](/data/prisma/crm). ## Mimari \[API nasıl kurulmuş] Haljet’in sunucu tarafı tek bir **NestJS** uygulamasıdır (`haljet-api`). Tüm istemciler (mobil, web, iç paneller) aynı API önekini kullanır: `api`. Geliştirme ortamında Swagger arayüzü `swagger` yolunda açılır; üretimde bu arayüz kapalıdır, Swagger belgesi yine de iç yapay zeka servisine verilir. ### Katmanlar ```mermaid flowchart TB Clients[İstemciler] --> API[NestJS API] API --> MySQL[(MySQL / Prisma)] API --> Mongo[(MongoDB)] API --> Redis[(Redis)] API --> Meili[MeiliSearch] API --> BQ[BigQuery] API --> Ext[Ödeme, fatura, SMS, HKS, Firebase] ``` | Katman | Görevi | | -------------- | ----------------------------------------------------------------------------------------------- | | HTTP | NestJS denetleyicileri. Varsayılan önek `api`. | | İş kuralı | Modül servisleri. Sipariş, ödeme, stok gibi kurallar burada. | | Olaylar | İç olay yayıcı. Sipariş oluşunca bildirim, rapor, Firestore senkronu gibi yan işler tetiklenir. | | Kuyruk | Bull + Redis. Transfer sevk, rapor toplama, mesaj yapay zekası. | | Zamanlanmış iş | Nest Schedule. Fatura, heatmap, grup değerlendirme, indeks yenileme. | | Kilit | MurLock (Redis). Aynı kullanıcının aynı anda iki sipariş oluşturması gibi yarışları keser. | Modül listesi: [Modül haritası](/structures). ### Güvenlik varsayılanı Uygulama genelinde **JWT erişim jetonu** zorunludur (`AtGuard`). Açık uçlar `@Public()` ile işaretlenir: giriş, bölge listesi, genel katalog, ödeme geri bildirimi, İzibiz web kancası gibi. | Mekanizma | Ne zaman kullanılır | | ------------------- | ---------------------------------------------------------------- | | JWT erişim jetonu | Neredeyse tüm uçlar. Süre: 1 gün. | | JWT yenileme jetonu | Oturum yenileme. Süre: 7 gün. | | API anahtarı | Özellikle `auth` uçları. | | Rol | Alıcı / satıcı / yetkili / yönetici ayrımı. | | İzin kodu | Örneğin `admin:buyer:full`, `officer:buyer-order-transfer:full`. | :::warning[Rol denetimi] Bazı denetleyicilerde rol etiketi vardır ama rol bekçisi bağlanmamıştır (`invoice/admin`, `invoice/officer`, `workflow/*`). Bu durumda JWT yeterlidir; rol kısıtı bekçi tarafından uygulanmaz. Detay: [Roller ve yetkiler](/overview/roles). ::: ### İstek ve yanıt Doğrulama `class-validator` ile yapılır. Dil, `Accept-Language` başlığından okunur; varsayılan dil **Türkçe**. Sayfalı listelerde yanıt gövdesi şu biçimdedir: asıl kayıtlar `data` altında, sayfa bilgisi isteğe bağlı `meta` altında (`page`, `limit`, `total`, `totalPages`). ### Çevredeki sistemler Bunların her biri [Altyapı ve dış sistemler](/overview/infrastructure) sayfasında açıklanır. | Sistem | Rol | | --------------- | ------------------------------------- | | MySQL | Ana ilişkisel kayıt | | MongoDB | Sipariş ve operasyon belgeleri | | Redis | Kuyruk, kilit, önbellek | | MeiliSearch | Ürün araması | | Firebase | Push, Firestore alıcı senkronu, dosya | | BigQuery | Analitik olay akışı | | PayTR / Paywall | Kart ve EFT ödeme | | İzibiz | E-fatura / e-arşiv | | HKS | Hal kayıt sistemi bildirimleri | | Netgsm | SMS | | Resend | E-posta | | Telegram | Operasyon uyarıları | | Google Gemini | İç yapay zeka metinleri | ### Uygulama içi dil API kodu İngilizce isimler kullanır. İş dilinde karşılıklar: | Kod adı | İş adı | | ---------------- | ---------------------------------- | | Buyer | Alıcı | | Seller | Satıcı | | Officer | Yetkili / saha veya depo personeli | | Admin | Yönetici | | Warehouse | Depo | | BuyerOrder | Alıcı siparişi | | Transfer | Teslimat taşıması | | FinancialAccount | Cari hesap | ## Altyapı ve dış sistemler \[API’nin konuştuğu dünya] Haljet API kendi başına siparişi yönetir; para, fatura, arama ve bildirim için dış servislere bağlanır. Bu sayfa **kodda yapılandırılmış** bağlantıları listeler. Kullanılmayan veya yorum satırına alınmış yollar ayrıca belirtilir. ### Veri ve çalışma zamanı | Sistem | Haljet’teki işi | | ---------------------- | --------------------------------------------------------------- | | **MySQL + Prisma** | Kullanıcı, ürün, depo tanımı, sepet, cari bakiye, adres, CRM. | | **MongoDB + Mongoose** | Sipariş, ödeme, stok hareketi, transfer, fatura, sohbet, rapor. | | **Redis** | Bull kuyrukları ve MurLock dağıtık kilit. | | **MeiliSearch** | Ürün arama indeksi. Saatlik tam yenileme (üretimde). | | **BigQuery** | Sipariş, arama, kayıt gibi analitik olaylar. | Verinin hangi tarafta durduğu: [Nerede ne tutulur](/data/storage). ### Kimlik ve bildirim | Sistem | İş | | ------------------------------ | ------------------------------------------------------------------------------------------------- | | **Firebase Auth** | Google / Firebase kimlik doğrulama, `firebaseUUID`. | | **Firebase Cloud Messaging** | Cihaz jetonu `UserDevice` tablosunda; sağlayıcı enum’u yalnız `FCM`. | | **Firebase Firestore** | Alıcı kaydı `buyer.firestore-sync` olayıyla senkronlanır. | | **Firebase Realtime Database** | Mesaj ve konum gibi anlık kanallar (mesaj dinleyicileri). | | **Netgsm** | SMS (telefon doğrulama). | | **Resend** | E-posta (doğrulama ve yönetici sipariş maili). | | **Telegram (Telegraf)** | Operasyon uyarıları. Bot `launchOptions: false` ile başlar; API mesaj gönderir, webhook dinlemez. | ### Ödeme Aktif kart yolu kodda **PayTR, başarısız olursa Paywall** şeklindedir. MagicPay servisi vardır; iframe üretim zincirinde yorum satırına alınmıştır. | Sağlayıcı | Koddaki platform değeri | Kullanım | | --------- | ----------------------- | ----------------------------------------------------- | | PayTR | `PAYTR` | Kart iframe, kayıtlı kart (`paytrUtoken`), EFT iframe | | Paywall | `PAYWALL` | PayTR başarısız olunca kart; webhook | | MagicPay | `MAGICPAY` | Modül mevcut, aktif fallback zincirinde değil | | Manuel | `MANUAL` | Havale onayı gibi operasyonel tahsilat | Ödeme durumu `PENDING`, `SUCCESS`, `FAIL`. Akış: [Ödeme](/flows/payment). ### Fatura ve yasal bildirim | Sistem | İş | | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **İzibiz** | E-fatura ve e-arşiv. Giden fatura `invoices` koleksiyonuna, gelen tedarikçi faturası `platformInvoices` koleksiyonuna yazılır. Web kancası `izibiz` yolunda herkese açıktır. | | **HKS** | Hal Kayıt Sistemi. Ürün kodları Prisma `ProductHks`; stok çıkış bildirimi sipariş faturası öncesinde denenir. Künye arama takibi `HksInvoiceTracker`. | Akış: [Fatura ve HKS](/flows/invoicing). ### Harita ve yapay zeka | Sistem | İş | | --------------------------- | ------------------------------------------------------------------------ | | **Google Maps** | Adres ve mesafe. | | **Google Gemini (Genkit)** | Genel AI soruları, mesaj kuyruğu, sipariş notu çıkarımı, bildirim metni. | | **Google uygulama kimliği** | BigQuery veri kümesi. | ### Kuyruklar Hepsi Redis üzerindeki Bull kuyruklarıdır. | Kuyruk | İş | | ------------------------------ | ------------------------------------ | | `haljet-ai` | Sohbet mesajını yapay zekaya işleme | | `transfer-operations` | Transfer sevk, araç faturası üretimi | | `report` | Ürün satış raporu toplama | | `warehouse-report` | Depo istatistik toplama | | `warehouse-coverage-recompute` | Teslimat kapsama alanı yeniden hesap | | `warehouse-product-stock` | Kuyruk kayıtlı; **işleyici yok** | ### Zamanlanmış işler Saatler, ilgili servislerin cron tanımından gelir (sunucu saatine bağlı; fatura işi İstanbul günü 07:00 olarak yazılmıştır). | Sıklık | Örnek işler | | ------------- | --------------------------------------------------------------------- | | Her 10 dakika | Depo stok bakımı | | Saatlik | MeiliSearch ürün indeksi, fatura cron, iade/transfer cron, fiyat mumu | | 06:00 | Depo stok | | 07:00 | Teslim edilmiş siparişler için fatura üretimi | | 08:00 | Alıcı cron | | 21:30 | HKS stok ön bildirimi | | Gece yarısı | Alıcı grup değerlendirme, heatmap, birçok rapor | | 02:00 | Alıcı yaşam döngüsü raporu (ikinci tur) | Bildirim cron’u kodda yorum satırına alınmıştır (`0 10` ve `0 17`). ## Platform genel hatları \[İşin büyük resmi] Haljet bir pazaryeri vitrini değil, **depo merkezli toptan tedarik** sistemidir. Alıcı bir ürün listesinden sipariş verir; sipariş bir depoya düşer; yetkililer hazırlar ve teslim eder; para ve fatura bu sürecin peşinden gelir. ### İşin özü Alıcıların çoğu işletmedir (restoran, market, otel). Her alıcının teslimat adresi, fatura bilgisi ve çoğu zaman bir **cari hesabı** vardır. Ürün fiyatı ülke genelinde tek değil; **depoya göre** stok ve fiyat vardır. Alıcının hangi depodan alışveriş yapacağı, adresinin düştüğü hizmet alanına göre belirlenir. ```mermaid flowchart LR A[Alıcı] --> B[Katalog ve sepet] B --> C[Sipariş] C --> D[Depo hazırlığı] D --> E[Teslimat] E --> F[Fatura ve cari] G[Satıcı tedariki] --> D ``` ### Ana parçalar Bu parçalar [yapılar](/structures) bölümünde ayrı ayrı anlatılır. Buradaki liste, iş dilindeki karşılıklarıdır. | İş parçası | Ne işe yarar | API’deki karşılığı | | ---------------- | ------------------------------------------- | ------------------------------------------ | | Hesap ve giriş | Telefon, e-posta veya Google ile kimlik | [Kimlik ve erişim](/structures/identity) | | Katalog | Ürün, kategori, KDV, birim, arama | [Ticaret](/structures/commerce) | | Sepet ve sipariş | Alışveriş, teslimat seçimi, sipariş belgesi | [Alışveriş akışı](/flows/shopping) | | Depo | Stok, fiyat kademesi, hizmet alanı, araç | [Lojistik](/structures/logistics) | | Teslimat | Kurye / müşteri teslim, araç rotası | [Hazırlık ve teslimat](/flows/fulfillment) | | Ödeme | Kart, havale, cari, kapıda tahsilat | [Ödeme akışı](/flows/payment) | | Cari | Bakiye, borç, kasa/palet sayımı | [Para ve fatura](/structures/money) | | Fatura | E-fatura / e-arşiv, HKS künye | [Fatura ve HKS](/flows/invoicing) | | CRM | Alıcı durumu, arama, not, grup | [Kişiler ve CRM](/structures/people) | | İletişim | Push, SMS, e-posta, sohbet | [İletişim](/structures/communication) | ### Günlük döngü 1. Alıcı uygulamadan ürün arar. Arama, MeiliSearch indeksinden gelir; fiyat ve stok ilgili depodan okunur. 2. Sepet MySQL’de tutulur. Sipariş oluşturulunca **MongoDB’de** tam bir sipariş belgesi yazılır; sepet temizlenir. 3. Ödeme kart ise önce ödeme bekler; havale ise onay bekler; cari veya kapıda ödeme ise sipariş doğrudan işleme alınabilir. 4. Depo yetkilisi siparişi onaylar, hazırlar, sevk eder. Stok çıkışı bu aşamada işlenir. 5. Teslimat kurye ise bir **transfer** kaydı açılır; araç rotasına bağlanabilir. 6. Teslimden sonra fatura ve HKS bildirimleri otomatik veya operasyonla üretilir. 7. Raporlar gece MongoDB’de toplanır; bazı olaylar BigQuery’ye de yazılır. Detaylı sıra: [Veri akışları](/flows). ### İki veri dünyası Platform kasıtlı olarak iki veritabanı kullanır: * **MySQL (Prisma)** — kullanıcı, ürün, depo tanımı, sepet, cari **bakiye**. Bunlar görece sabit, ilişkili kayıtlardır. * **MongoDB** — sipariş, ödeme, stok hareketi, transfer, fatura, rapor. Bunlar belge niteliğinde, iç içe ve yüksek hacimli kayıtlardır. Neden böyle ayrıldığı: [Nerede ne tutulur](/data/storage). ### Bu belgede olmayanlar Kodda olmayan mobil uygulama ekranları, ayrı bir frontend reposu veya pazarlama vaatleri burada anlatılmaz. Dış servislerin (PayTR, İzibiz, HKS) kendi panelleri de bu sitenin konusu değildir; Haljet’in onlarla **nasıl konuştuğu** anlatılır. ## Roller ve yetkiler \[Kim neye erişir] Her hesap bir **kullanıcı** kaydıdır. Kullanıcının tipi, hangi uygulamayı ve hangi uçları kullanacağını belirler. Tip, Prisma `UserType` enum’udur. ### Kullanıcı tipleri | Tip | Anlamı | Profil tablosu | | --------- | --------------------------------------- | ------------------------------------ | | `BUYER` | Alıcı işletme. Sipariş verir. | `Buyer` (kullanıcıyla 1:1) | | `SELLER` | Tedarikçi. Depoya mal sağlar. | `Seller` (kullanıcı isteğe bağlıdır) | | `OFFICER` | Depo / saha / satın alma personeli. | `Officer` | | `ADMIN` | Depo ve alıcı yöneten yönetici. | `Admin` | | `SYSTEM` | İnsan hesabı değil, sistem kullanıcısı. | — | Aynı kullanıcı kaydı bu tiplerden **birini** taşır. Alıcı, satıcı, yetkili ve yönetici profilleri kullanıcıya 1:1 bağlanır. ### Yetkili rolleri Yetkili (`OFFICER`) ek olarak `OfficerRole` taşır. Bu, depo içi iş bölümüdür; JWT’deki ana tip yine `OFFICER` kalır. | Rol | Kullanıldığı yer (kodda görülen) | | ---------------------- | -------------------------------------- | | `MANAGER` | Yönetim | | `MARKETING` | Yeni alıcı kaydında bildirim alan ekip | | `HEADOF_MARKETING` | Pazarlama yönetimi | | `WORKER` | Depo işçiliği | | `DRIVER` | Teslimat | | `PURCHASING` | Satın alma | | `PURCHASING_ASSISTANT` | Satın alma yardımcısı | | `ADMIN_ASSISTANT` | Yönetici asistanı | | `IT` | Bilgi işlem | | `IK` | İnsan kaynakları | Alıcı CRM notlarında da `officerRole` tutulabilir; notun hangi ekibe ait olduğunu işaretler. ### Giriş nasıl çalışır 1. İstemci çoğu `auth` ucunda **API anahtarı** gönderir. 2. Telefon kodu, e-posta kodu veya Google / Firebase kimliği doğrulanır. 3. API **erişim** ve **yenileme** jetonu üretir. Erişim jetonunun yükünde kullanıcı kimliği, rol ve izin listesi vardır. 4. Sonraki istekler `Authorization: Bearer` ile gider. 5. Çıkışta yenileme jetonu silinir; cihaz kaydı da cihaz kimliğiyle silinebilir. Akış: [Kayıt ve giriş](/flows/registration). ### İzin kodları Rol tek başına yetmezse `UserPermission` tablosundaki kodlar kullanılır. Kodda şu an bağlanan kodlar: | İzin | Nerede | | ------------------------------------- | ---------------------------------------- | | `admin:buyer:full` | Yönetici alıcı CRM ve alıcı panosu | | `admin:post:view` / `admin:post:full` | İçerik (slider, banner, hikâye, akademi) | | `admin:unit:full` / `admin:vat:full` | Birim ve KDV tanımları | | `officer:buyer-order-transfer:full` | Yetkilinin sipariş transferi | İzinler `PermissionsGuard` ile denetlenir; jeton içindeki `permissions` dizisine bakılır. ### Uçların kime açık olduğu Aşağıdaki özet, denetleyicilerdeki yol ve bekçilerden derlenmiştir. Tam yol listesi ilgili yapı sayfalarındadır. | Alan | Tipik erişim | | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | `auth`, `area`, `catalog/public`, `ai`, `price-analytics/public`, `payment/*`, `izibiz` | Açık veya API anahtarı | | `basket/buyer`, `purchase/buyer`, `order/buyer` | Alıcı | | `procurement/seller` | Kimliği doğrulanmış (satıcı amaçlı; sınıf düzeyinde rol bekçisi yok) | | `warehouse/*`, `stock`, `order/officer` | Yetkili ve/veya yönetici | | `admin/*`, `report/*`, `buyer-group/admin` | Yönetici (raporlarda yetkili de var; pazarlama raporu yalnız yönetici) | | `message` | Çoğu uçta kimliği doğrulanmış herhangi bir tip | :::info[Teknik not] `invoice/admin`, `invoice/officer` ve `workflow/*` uçlarında rol etiketi vardır, `RoleGuard` yoktur. Bu, “niyet edilen rol” ile “fiilen uygulanan kısıt”ın ayrıldığı yerdir. ::: ### Alıcı–yönetici–yetkili ilişkisi Bir alıcı yalnızca kullanıcı değildir. Yönetici ile arasında `AdminBuyer` CRM kaydı vardır (sipariş sayıları, arama, durum). Yetkililer bu kayda `AdminBuyerOfficer` ile bağlanır. Depo tarafında yetkili, `AdminOfficer` ile depoya bağlanır. Şema: [CRM ve alıcı grupları](/data/prisma/crm). ## Hazırlık ve teslimat \[Depodan kapıya] Ödemesi kapanmış sipariş depo kuyruğundadır (`PENDING`). Bundan sonrası yetkili ve yönetici işidir. ### Onay ve hazırlık :::steps ##### Onay Yetkili siparişi `APPROVED` yapar. ##### Hazırlık `prepareOrder` kalemlere hazır miktar, kasa/palet bilgisi işler. Sipariş `IN_PROGRESS`, kalemler hazır olunca `READY`. Ödeme bloğu yeniden hesaplanır. Hazırlık fotoğrafları `preparedImages` dizisindedir. ##### Sevk `shipOrder` siparişi `SHIPPED` yapar. FIFO lot seçilir, `stockExits` yazılır, kalemlere çıkış referansı işlenir. İptal kalem + kart ödenmişse kısmi iade denenir. `buyer-order.changed` yayınlanır. ::: ### Teslimat Kurye (`COURIER`) siparişinde aktif transfer yoksa `BuyerOrderTransfer` açılır, kalemlere ve siparişin `transfers` dizisine bağlanır. Yetkili teslim edince transfer `DELIVERED`, sipariş `deliverOrder` ile `DELIVERED`. Müşteri teslimi (`CUSTOMER`) transfer kaydı açmaz; teslim sipariş üzerinden işlenir. ### Araç seferi Birden fazla sipariş transferi bir `WarehouseVehicleTransfer` belgesine bağlanır. Seferde şoför, araç, mesafe, sürüş süresi, başlangıç/bitiş, GPS noktaları ve kapıda tahsilat listesi durur. Sevk ve araç faturası `transfer-operations` kuyruğuna düşebilir. Araç fatura durumu: `PENDING`, `PROCESSING`, `COMPLETED`, `PARTIAL`. ### İade Teslim edilmiş (veya iadesi reddedilmiş) kalem için alıcı iade talebi açar. Medya geçici `returnMediaUploads` koleksiyonuna yüklenir. Talep `buyerOrderReturns` belgesidir. Yönetici: bekleyen → onay / red / iptal. Yetkili onaylı talebi işleme alır ve tamamlar. Tamamlanınca kalem `RETURNED`. Alıcı kendi bekleyen talebini iptal ederse kalem yeniden `DELIVERED` görünür. İade nedenleri: çürük, ezik, kalitesiz, farklı ürün, fazla. ### Sorun İade değildir. Teslimat süresi, teslimat tipi, kalite, fatura veya diğer. Durum: açık, görüldü, çözüldü. ### Stok girişi (tedarik) Satış çıkışının tersi, satıcıdan depoya giriştir. Eski yolda `warehouseProductStockIn` yazılır ve (taslak değilse) Prisma stok artar. Yeni yolda `StockEntry` lotu kalan miktar taşır. HKS ham künye eski giriş belgesinde durabilir. Detaylı belgeler: [Stok ve transfer](/data/mongodb/stock-transfers). ## Akışlara bakış \[İşin sırası] Yapı sayfaları “hangi parça ne işe yarar?” sorusunu cevaplar. Bu bölüm “bir iş nasıl ilerler?” sorusunu cevaplar. Adımlar ilgili servislerin çağrı sırasından alınmıştır. ### Ana yol Çoğu alıcı bu sırayı izler: ```mermaid flowchart LR R[Kayıt] --> S[Katalog ve sepet] S --> P[Sipariş] P --> Pay[Ödeme] Pay --> F[Hazırlık] F --> D[Teslimat] D --> I[Fatura] ``` | Adım | Sayfa | Kim | | ---------------------------- | ------------------------------------------ | ----------------------- | | Hesap açma ve giriş | [Kayıt ve giriş](/flows/registration) | Alıcı (ve diğer tipler) | | Ürün, sepet, sipariş belgesi | [Alışveriş](/flows/shopping) | Alıcı, yetkili | | Kart, havale, cari | [Ödeme](/flows/payment) | Alıcı, sistem, yetkili | | Onay, hazırlık, stok, kurye | [Hazırlık ve teslimat](/flows/fulfillment) | Yetkili, yönetici | | E-belge ve HKS | [Fatura ve HKS](/flows/invoicing) | Sistem, operasyon | | Push, kutu, SMS, mail | [Bildirimler](/flows/notifications) | Sistem | | Özet tablolar ve BigQuery | [Raporlama](/flows/reporting) | Yönetici, yetkili | ### Yan yollar Bunlar ana yolu kesmez, ona bağlanır: * **İade** — teslim edilmiş kalem üzerinden; yönetici onaylar, yetkili işler. [Sipariş ve iade](/data/mongodb/orders) * **Sorun bildirimi** — teslimat veya kalite. Ayrı `buyerOrderIssues` belgesi. * **Cari düzeltme** — sipariş dışında elle hareket. [Para ve fatura](/structures/money) * **Stok alımı** — satıcıdan depoya giriş. [Lojistik](/structures/logistics) ### Durum makinesi (sipariş) Sipariş belgesinin `status` alanı tek bir yaşam çizgisidir. Kart siparişi `PAYMENT_FAILED` ile doğar (ödeme bekler); havale `PAYMENT_WAITING`; cari veya kapıda ödeme `PENDING` ile başlar. Ödeme düşünce `PENDING` olur. Sonra onay → hazırlık → hazır → sevk → teslim. İptal ve iade bu çizgiyi keser. Kalem üzerindeki `RETURN_*` değerleri siparişin kendisinden ayrı, iade talebinin yansımasıdır. Görsel ve tablo: [Alışveriş](/flows/shopping#sipariş-durumları). ## Fatura ve HKS \[Yasal belge ve künye] Fatura, sipariş teslim edildikten sonra üretilir. HKS bildirimi fatura öncesinde **elden geldiğince** denenir; başarısızlık faturayı tek başına durdurmak zorunda değildir (kodda best-effort). ### Ne zaman kesilir? `OrderInvoiceService` her gün 07:00’de (İstanbul) son teslim tarihi uygun alıcılar için fatura üretimini tarar. Operasyon ayrıca sipariş veya tarih aralığıyla da tetikleyebilir. Aynı siparişe ikinci kez fatura gömülmez: belgede `invoice` alanı doluysa atlanır. Üretim sırasında kullanıcı kilidi (MurLock) alınır. ### Üretim sırası :::steps ##### Adres kontrolü Alıcının fatura adresinde vergi / kimlik / daire / doğum tarihi gibi alanlar doğrulanır. Eksik bilgi CRM problem tipi ile de işaretlenebilir. ##### HKS Sipariş kalemleri HKS ürünüyse stok çıkış bildirimi kurulur, HKS API’ye gönderilir, kalan miktar künye no ile güncellenmeye çalışılır. Yanıt kalemin `hksNotifications` dizisine yazılır. ##### İzibiz Kalemler e-belge satırına çevrilir. HKS’li ürünlerde ilgili profil seçilir. İzibiz belge numarası `InvoiceSequence` tablosundan (tip + önek + yıl) ilerler. ##### Kayıt Mongo `invoices` belgesi oluşur. Siparişin içine kısa `invoice` özeti (belge no, UUID, tarih, tutar, vergi) gömülür. Gerekirse cari hareket yazılır. ::: ### Gelen tedarikçi faturası İzibiz gelen kutusu `platformInvoices` koleksiyonuna yazılır. `stockProcessed` / `stockNotApplicable` bayrakları stok girişine bağlanıp bağlanmadığını gösterir. Web kancası `izibiz` yolundadır ve herkese açıktır (sağlayıcı çağrısı). ### HKS’nin diğer yüzü HKS yalnız fatura anında değildir: * Ürün kartında `ProductHks` kodları * Depo ve coğrafyada `hksCode` * Eski stok girişinde `hksRaw` * `HksInvoiceTracker` ile künye arama sayacı * 21:30 cron’u stok ön bildirimi HKS ürün tipi ve şube sorguları `HksService` üzerindendir; ayrı bir HTTP denetleyicisi yoktur. Şema: [Cari ve fatura numarası](/data/prisma/finance), [Cari ve fatura (Mongo)](/data/mongodb/finance-invoices). ## Bildirimler \[Kime, hangi kanaldan] Bildirim tek bir kutu değildir. Aynı olay birden fazla kanala gidebilir. Kanallar [İletişim](/structures/communication) sayfasında ayrılmıştır. ### Sipariş | Durum | Kanal | | ------------------------------------------------------------- | -------------------------------------- | | Yeni `PENDING` (oluşum veya ödeme sonrası) | Yönetici e-posta, alıcı push, Telegram | | Onay, hazırlık, hazır, sevk, teslim, iptal, ödeme zaman aşımı | Alıcı push + Mongo kutu | Durum değişimi `buyer-order.changed` üzerinden de aynı bildirim servisine bağlanır. ### Kayıt Yeni alıcı: Telegram bilgi mesajı + pazarlama yetkililerine push. Firestore senkronu bildirim değil, alıcı kartının kopyasıdır. ### Yönetici yayını Yönetici `notification` ucundan metin gönderir. İsteğe bağlı segment kullanıcı id’lerini çözer. Cihaz jetonları parçalanır, FCM’e gider, aynı içerik `notifications` koleksiyonuna `isRead: false` olarak yazılır. ### Görev ve sohbet Görev oluşturulunca veya not eklenince atanan kullanıcılara push + kutu gider. Sohbet olayları anlık kanala ve ilgili kullanıcılara bildirime bağlanır. ### SMS ve e-posta SMS ağırlıklı olarak **doğrulama kodu** içindir (Netgsm). E-posta doğrulama ve yönetici yeni sipariş maili içindir (Resend). Kampanya SMS’i bu akışta ayrı bir ürün gibi belgelenmez; kodda asıl kullanım doğrulamadır. ### Okunma Kutu kaydının `isRead` alanı Mongo `notifications` belgesindedir. Sohbette okunma konuşma kullanıcısı üzerindeki `unreadCount` / `lastReadAt` ve kullanıcı tablosundaki `unreadMessageCount` ile izlenir. ## Ödeme \[Paranın siparişe bağlanması] Ödeme, sipariş belgesindeki `purchase` bloğu ile Mongo `payments` kaydının birlikte işlemesidir. Sağlayıcı sonucu gelmeden kart siparişi depoda işlenmez. ### Yöntemler Sipariş ödeme yöntemi `PurchasePaymentMethod` enum’udur: | Değer | Alıcı ne yapar | | ---------- | --------------------------------------------------------------- | | `CARD` | Kart / kayıtlı kart. Sağlayıcı iframe veya kayıtlı kart çekimi. | | `TRANSFER` | EFT / havale. Bildirim + yetkili onayı. | | `ACCOUNT` | Cari bakiye. Sipariş anında düşülür. | | `CASH` | Nakit (kapı / operasyon). | | `CHECK` | Çek. | Çevrimiçi / çevrimdışı ayrımı `ONLINE` / `OFFLINE` alanındadır. Alıcının `isOfflinePayment` bayrağı kapı tahsilatına izin verir. ### Kart :::steps ##### Sipariş Kart siparişi `PAYMENT_FAILED` ile doğar. Alıcı ödeme ucunu çağırır. ##### İframe Önce PayTR denenir. Başarısızsa Paywall. MagicPay servisi kodda vardır, bu zincirde açık değildir. Bekleyen `payments` kaydı `PENDING` yazılır. ##### Geri bildirim PayTR veya Paywall webhook’u ödemeyi `SUCCESS` veya `FAIL` yapar ve `payment.updated` yayınlar. ##### Sipariş güncellenir Başarı: sipariş `PENDING` olur, `purchase.isPaid` dolu, cari netleşir, `buyer-order.created` o anda yayınlanır. Başarısızlık: sipariş ödeme başarısız kalır. ::: Kayıtlı kart: kullanıcının `paytrUtoken` alanı PayTR saklı kart içindir. ### Havale Alıcı EFT iframe veya “havale bildirdim” yolunu kullanır. Sipariş `PAYMENT_WAITING` kalır; banka, IBAN, dekont ve bildirim zamanı `purchase.transfer` içinde durur. Yetkili onaylayınca **manuel** başarılı ödeme kaydı oluşur ve sipariş `PENDING` olur. ### Cari Bakiye yeterliyse sipariş doğrudan `PENDING` olabilir. Hareket tipi `USE_BALANCE_FOR_PURCHASE`. İptalde `REFUND_BALANCE_FOR_ORDER` veya alıcının seçimine göre `TRANSFER_TO_BALANCE_FOR_ORDER`. Kart iadesi başarısızsa tutar `REFUND_FALLBACK_TO_BALANCE_FOR_ORDER` ile cariye yazılır. ### Kapıda tahsilat Çevrimdışı sipariş sevk edilince borç `OFFLINE_PURCHASE_FOR_ORDER` ile cariye işlenebilir. Teslimde tahsilat `OFFLINE_PAYMENT_FOR_ORDER` ile kapanır. Kurye aracındaki `collectedPayments` tahsilatın saha kaydıdır. ### Sevk sonrası tutar farkı Hazırlıkta miktar değişirse ödeme yeniden hesaplanır. Kart ödenmiş ve iptal kalem varsa kısmi iade denenir. Sevkta tahsil ile net fark `ORDER_AMOUNT_DIFFERENCE` hareketine dönebilir. ### Ödeme kaydı alanları `payments` koleksiyonu sadedir: kullanıcı, platform (`PAYTR` / `PAYWALL` / `MAGICPAY` / `MANUAL`), yöntem, işlem no, sipariş id, durum (`PENDING` / `SUCCESS` / `FAIL`), tutar, hata kodu ve mesajı. Platform, sipariş id ve tutar sonradan değişmez (şemada immutable). ## Kayıt ve giriş \[Hesap nasıl açılır] Bu akış `auth` ve `user` modüllerinden okunur. Alıcı kaydı en zengin yoldur; satıcı, yetkili ve yönetici kayıtları da aynı çekirdeği kullanır. ### Alıcı kaydı :::steps ##### Uyarılar Kayıt isteği gelince operasyon Telegram kanalına bilgi gider. Pazarlama rolündeki yetkililere Firebase bildirimi gider. ##### Kod doğrulama Telefon, e-posta veya Firebase kimliği doğrulanır. Telefon kodu ülke + numara ile `PhoneVerification` satırındadır. E-posta kodu `EmailVerification` satırındadır (e-posta benzersiz). ##### Kullanıcı ve alıcı Prisma’da `User` oluşur (`type = BUYER`). Ardından `Buyer` ve global yöneticiye bağlı `AdminBuyer` kaydı yazılır. ##### Yan etkiler `buyer.firestore-sync` olayı Firestore’a gider. ##### Kayıt ödülü Aktif `BUYER_SIGNUP` tanımı varsa cariye `REWARD` hareketi yazılır. Ödül hata verirse kayıt yine tamamlanır; hata yalnızca loglanır. ##### Analitik ve oturum BigQuery’ye alıcı kayıt olayı yazılır. Erişim ve yenileme jetonu üretilir; yenileme özeti kullanıcı satırına yazılır. ::: ### Kayıt ödülü Ödül tanımları veritabanında değildir; `financial` modülündeki `REWARDS` listesindedir. `grantSignupReward` bu listeden `BUYER_SIGNUP` kodlu, `isActive` olan ve tarih aralığına uyan kayıtları alır. Bitiş tarihi boşsa süre sınırsızdır. Eşleşen tanım yoksa hiçbir hareket yazılmaz. Her tanım, kendi `warehouseId` deposundaki cariye bir işlem açar. Depo bulunamazsa o tanım atlanır. Tutar `TransactionType.REWARD` (artı bakiye) ile gider; açıklama tanımın `name` alanıdır, `transactionTypeCode` tanımın `id` değeridir. Şu anki tek tanım: | Alan | Değer | Anlamı | | ----------- | ----------------------------- | -------------------- | | id | `BUYER_SIGNUP_REWARD_2026_08` | Hareket kodu | | code | `BUYER_SIGNUP` | Kayıt ödülü türü | | name | Yeni Üye Kayıt Ödülü | Cari açıklaması | | amount | 250 | Cariye yazılan tutar | | warehouseId | 1 | Hangi depo carisi | | startDate | 2026-08-20 | Bu tarihten itibaren | | endDate | boş | Bitiş yok | | isActive | true | Kullanılıyor | Tanım listesine aynı koddan birden fazla aktif satır konursa her biri ayrı hareket üretir. Yalnız yeni alıcı kaydı bu yolu çağırır; satıcı / yetkili / yönetici kaydı çağırmaz. Cari tarafı: [Para ve fatura](/structures/money). Hareket tipi: [Cari ve fatura](/data/mongodb/finance-invoices). ### Giriş Giriş üç yoldan biridir: telefon kaydı, Firebase kimlik jetonu veya parola (bcrypt). Başarılı girişte jeton yenilenir; Firebase UUID güncellenebilir. Çıkışta yenileme jetonu temizlenir. Verilen cihaz kimliği varsa `UserDevice` silinir. ### Cihaz Push için cihaz adı, cihaz kimliği ve FCM jetonu `UserDevice` tablosuna yazılır. Aynı kullanıcı + cihaz çifti tektir. Sağlayıcı enum’u yalnız `FCM`. ### Veri nerede? | Kayıt | Depo | | --------------------------------------- | ------------------------------------------------ | | Kullanıcı, alıcı, CRM bağlantısı, cihaz | MySQL | | Doğrulama kodları | MySQL | | Alıcı kopyası (sonradan siparişte) | Mongo gömülü | | Kayıt ödülü (varsa) | Prisma cari bakiye + Mongo `accountTransactions` | | Kayıt olayı | BigQuery `buyer_registrations` | Şema: [Kimlik ve izinler](/data/prisma/identity). ## Raporlama \[Özet nereden gelir] İki katman vardır: 1. **Mongo raporları** — gün ve depo bazında önceden toplanmış tablolar. Ekran bunları okur. 2. **BigQuery** — tekil olaylar. Analitik ve geriye dönük sorgu. ### Ne tetikler? | Rapor | Tetik | | ------------------- | --------------------------------------------------------------------------------------------------- | | Ürün satış | `product-sale.recorded` kuyruğu; teslim / iptal / zaman aşımı / iade olunca günün yeniden kurulması | | Ürün alım | Stok giriş-çıkış olaylarına bağlı servis | | Alıcı | Gece yarısı cron | | Alıcı yaşam döngüsü | Gece yarısı ve 02:00 cron | | Cari | Gece yarısı cron | | Depo istatistik | `warehouse-report` kuyruğu | | Heatmap | Gece yarısı (sipariş ve depo ayrı koleksiyonlar) | ### Satış satırı nereden gelir? Sipariş oluşunca dinleyici satış olayını yayınlar. Kalemler depo, tarih ve ürün bazında `productSalesReports` belgesine eklenir. Sipariş iptal veya iade olursa o günün belgesi yeniden hesaplanır; bu yüzden rapor “anlık sipariş listesi” değil, **düzeltilmiş günlük özet**tir. ### BigQuery’ye ne zaman yazılır? Canlı yazım (track servisi): * Alıcı kaydı * Sipariş ve satılan kalem (oluşum) * Adres kaydı * Fiyat değişimi * Arama bulundu / bulunamadı * Ürün görüntüleme ve ürün talebi (ilgili servisler) Toplu aktarım: `report/bigquery-migration` teslim edilmiş siparişleri ve adresleri geri yükler. Tablo alanları: [BigQuery](/data/bigquery). ### Raporu sipariş belgesinden ayırın Sipariş gerçeği `buyerOrders` koleksiyonudur. Rapor belgesi ondan türetilmiş bir **özettir**. Anlaşmazlıkta sipariş belgesi esas alınır; rapor gecikmeli veya o gün için yeniden kurulmuş olabilir. ## Alışveriş \[Sepetten sipariş belgesine] Alıcının gördüğü “sipariş ver” düğmesi aslında birkaç hizmeti sırayla çağırır. Bu sayfa o sırayı anlatır. ### 1. Katalog ve arama Alıcının seçili teslimat adresi, hangi **depodan** alışveriş yapacağını belirler. Arama MeiliSearch `product` indeksinde çalışır; filtreler depo, şirket tipi ve kategoridir. Sonuçlar o deponun fiyat kademeleriyle doldurulur. Favori Prisma `ProductFavorite` tablosundadır. Ürün talebi Mongo `productRequests` koleksiyonuna düşer. ### 2. Sepet Sepete ekleme Prisma `ProductBasket` satırını yazar veya günceller (kullanıcı + ürün tektir). Sepet henüz sipariş değildir; stok rezervasyonu bu adımda anlatılan kod yolunda yoktur. ### 3. Önizleme Satın alma önizlemesi siparişi kaydetmeden şunları kurar: * Alıcı, teslimat adresi, fatura adresi * Depo kararı ve asgari sepet kuralı * Cari bakiye * Aktif sepet satırları ve depo fiyatları * Kargo, indirim, içeride taşıma, cari kullanımı * Teslimat bloğu (tarih, tür, mesafe) Sonuç, henüz kaydedilmemiş bir sipariş belgesi görünümüdür. ### 4. Sipariş oluşturma Aynı kullanıcı için kilit alınır. Ödeme bekleyen eski siparişler iptal edilebilir. Sonra Mongo’da `buyerOrders` belgesi oluşur. İlk durum ödeme yöntemine bağlıdır: | Yöntem | İlk durum | Neden | | ---------------------------------------------- | ----------------- | ----------------------------------------------- | | Kart (`CARD`) | `PAYMENT_FAILED` | Henüz sağlayıcıdan başarı gelmedi; ödeme bekler | | Havale (`TRANSFER`) | `PAYMENT_WAITING` | Operasyon onayı bekler | | Cari (`ACCOUNT`) veya çevrimdışı / sıfır tutar | `PENDING` | Tahsilat sipariş anında kapanmış sayılır | Cari kullanıldıysa `USE_BALANCE_FOR_PURCHASE` hareketi yazılır. `PENDING` olan sipariş `buyer-order.created` olayını üretir ve sepet temizlenir. Kart/havale siparişinde bu olay **ödeme düşünce** üretilir. ### Sipariş oluşunca ne olur? `buyer-order.created` dinleyicisi (kodda) şunları yapar: * Bölge kilidi bildirimi (kapsama alanı) * Yönetici e-postası ve alıcı push * Telegram uyarısı * `AdminBuyer` sipariş sayacı * Favori upsert * BigQuery sipariş ve kalem satırları * Sipariş notundan AI çıkarımı * CRM notlarının yetkili notuna aktarımı * Satış raporu kuyruğu ### Sipariş durumları Sipariş belgesi ve kalemler aynı enum’u paylaşır. Aşağıdakiler **sipariş düzeyi** yaşam çizgisidir. ```mermaid stateDiagram-v2 [*] --> PAYMENT_FAILED: Kart [*] --> PAYMENT_WAITING: Havale [*] --> PENDING: Cari veya kapıda PAYMENT_FAILED --> PENDING: Kart başarılı PAYMENT_WAITING --> PENDING: Havale onay PENDING --> APPROVED: Onay APPROVED --> IN_PROGRESS: Hazırlık IN_PROGRESS --> READY: Kalemler hazır READY --> SHIPPED: Sevk SHIPPED --> DELIVERED: Teslim PENDING --> CANCELLED: İptal APPROVED --> CANCELLED: İptal SHIPPED --> RETURNED: İade / iade transferi ``` | Durum | Anlamı | | ----------------- | ---------------------------------- | | `PAYMENT_WAITING` | Havale bildirimi / onay bekleniyor | | `PAYMENT_FAILED` | Kart henüz başarılı değil | | `PAYMENT_TIMEOUT` | Ödeme süresi doldu | | `PENDING` | Depo kuyruğunda | | `APPROVED` | Onaylandı | | `IN_PROGRESS` | Hazırlanıyor | | `READY` | Teslime hazır | | `SHIPPED` | Yola çıktı; stok çıkışı bu adımda | | `DELIVERED` | Teslim edildi | | `CANCELLED` | İptal | | `RETURNED` | İade tamam | Kalem üzerindeki `RETURN_PENDING`, `RETURN_APPROVED`, `RETURN_IN_PROGRESS`, `RETURN_REJECTED` değerleri açık bir iade talebinin yansımasıdır; siparişin ana durumundan ayrı tutulur. Sonraki adım: [Ödeme](/flows/payment) veya [Hazırlık ve teslimat](/flows/fulfillment). Belge alanları: [Sipariş ve iade](/data/mongodb/orders). ## BigQuery \[Olay tabloları] Kaynak: `src/bigquery/bigquery.const.ts`. Her tabloda zorunlu `timestamp` (TIMESTAMP) vardır. Aşağıdaki alanlar buna eklenir. Canlı yazım ve geri yükleme: [Raporlama](/flows/reporting). Bu tablolar sipariş gerçeğinin yerine geçmez. ### orders | Alan | Tip | Zorunlu | Anlamı | | ------------------------------ | ------- | ------- | ------------------- | | order\_code | STRING | evet | Sipariş kodu | | buyer\_id | INTEGER | | Alıcı | | buyer\_name | STRING | | Ad | | buyer\_type | STRING | | Şirket tipi | | total\_price | FLOAT | | Tutar | | order\_status | STRING | | Durum | | delivery\_latitude / longitude | FLOAT | | Teslimat koordinatı | ### order\_products | Alan | Tip | Anlamı | | -------------- | --------------- | ------------ | | order\_code | STRING, zorunlu | Sipariş | | product\_id | INTEGER | Ürün | | product\_name | STRING | Ad | | product\_price | FLOAT | Fiyat | | quantity\_sold | FLOAT | Miktar | | unit | STRING | Birim | | total\_price | FLOAT | Satır tutarı | | status | STRING | Kalem durumu | | category | STRING | Kategori | ### buyer\_addresses `buyer_id`, `buyer_name`, `buyer_type`, `address_latitude`, `address_longitude`, `min_basket_amount`. ### product\_price\_changes `product_id`, `product_name`, `category`, `max_price`, `warehouse_id`. ### product\_search\_not\_found / product\_search\_found `search_query`, `searched_by_id`, `searched_by_name`. ### product\_views `product_id`, `product_name`, `category`, `max_price`, `warehouse_id`, `viewed_by_id`, `viewed_by_name`. ### buyer\_registrations `buyer_id`, `buyer_name`, `buyer_type`, `email`, `phone`, `reference_code`. ### product\_requests `product_id`, `product_name`, `is_existing_product`, `note`, `amount`, `requested_by_id`, `requested_by_name`. Tablo adları enum’da: `orders`, `order_products`, `buyer_addresses`, `product_price_changes`, `product_search_not_found`, `product_search_found`, `product_views`, `buyer_registrations`, `product_requests`. ## Veri katmanları \[Kayıt nerede yaşar] Haljet tek bir “veritabanı” değildir. Her katman farklı bir soruyu hızlı cevaplamak içindir. | Katman | Soru | Teknoloji | | -------------- | ----------------------------------------- | ----------------------- | | İlişkisel | Bu kullanıcı kim, ürün nedir, bakiye kaç? | MySQL, Prisma, 57 model | | Belge | Bu siparişin tüm hikâyesi nedir? | MongoDB, Mongoose | | Arama | Bu isim hangi ürüne benzer? | MeiliSearch | | Kuyruk / kilit | Bu iş şimdi mi, sonra mı, tek mi? | Redis, Bull, MurLock | | Analitik | Bu olaylar zaman içinde nasıl? | BigQuery | Hangi iş kaydının hangi katmanda olduğu: [Nerede ne tutulur](/data/storage). ### MySQL (Prisma) Tablo adları model adlarıyla aynıdır (`@@map` yoktur). Soft delete bazı tablolarda `deletedAt` ile yapılır (`User`, `Category`, `Post`, `SurveyQuestion`). Bölümler: * [Genel bakış](/data/prisma) * [Kimlik ve izinler](/data/prisma/identity) * [Coğrafya ve adres](/data/prisma/geography) * [Katalog ve stok kartı](/data/prisma/catalog) * [Depo ve teslimat alanı](/data/prisma/warehouse) * [Cari ve fatura numarası](/data/prisma/finance) * [CRM ve alıcı grupları](/data/prisma/crm) * [Enum değerleri](/data/prisma/enums) ### MongoDB Koleksiyonlar sipariş, hareket ve özet belgeleridir. Prisma’daki kullanıcı/ürün/depo, Mongo belgelerine **kopya** olarak gömülür. Kopya, belgenin yazıldığı andaki fotoğraftır; ana kart sonradan değişse bile sipariş o anki isim ve vergi ile kalır. Bölümler: * [Genel bakış](/data/mongodb) * [Sipariş ve iade](/data/mongodb/orders) * [Stok ve transfer](/data/mongodb/stock-transfers) * [Cari ve fatura](/data/mongodb/finance-invoices) * [İletişim ve iş akışı](/data/mongodb/communication) * [Raporlar ve fiyat](/data/mongodb/reports) * [Durum değerleri](/data/mongodb/enums) ### BigQuery Canlı olay tabloları: [BigQuery](/data/bigquery). ## Nerede ne tutulur \[Çift kayıt yok, çift soru var] Aynı kavram bazen iki yerde görünür. Bu hata değil: biri **kart**, biri **hareket** veya **anlık kopya**dır. ### Hızlı tablo | Kavram | Asıl kayıt | Hareket / belge | Kopya / indeks | | ----------------- | -------------------------------- | --------------------------- | -------------------------------- | | Kullanıcı | MySQL `User` | Mongo `userLogs` | Siparişte `UserCopy` | | Alıcı | MySQL `Buyer` | CRM ve grup değerlendirme | Siparişte `BuyerCopy` | | Ürün | MySQL `Product` | — | Sipariş kalemi, MeiliSearch | | Depo stok miktarı | MySQL `WarehouseProduct.stock` | Mongo giriş/çıkış | Sipariş kalemindeki referanslar | | Cari bakiye | MySQL `FinancialAccount.balance` | Mongo `accountTransactions` | — | | Sepet | MySQL `ProductBasket` | Sipariş oluşunca silinir | — | | Sipariş | — | Mongo `buyerOrders` | BigQuery `orders` | | Ödeme işlemi | — | Mongo `payments` | Siparişte `purchase.payment` ref | | Fatura | MySQL sıra numarası | Mongo `invoices` | Siparişte `invoice` özeti | | Arama | — | — | MeiliSearch `product` | | Push jetonu | MySQL `UserDevice` | — | `UserCopy.devices` | ### Neden sipariş MySQL’de değil? Bir sipariş kalem, teslimat, ödeme kırılımı, geçmiş, fatura özeti ve transfer bağlantısını **tek belge** olarak taşır. İlişkisel tablolara bölmek N+1 ve şema evrimi maliyeti doğurur. Bu yüzden yaşam döngüsü Mongo’dadır. ### Neden bakiye MySQL’de? Bakiye sık okunur, tek sayıdır, kullanıcı+depo ile tektir. Defter ise append-only belgedir. Okuma bakiyeden, tartışma defterden yapılır. Defterdeki `balance` alanı **o hareketten sonraki** bakiyenin anlık görüntüsüdür. ### Gömülü kopya ne demek? Sipariş yazılırken alıcı adı, depo adı, ürün birimi belgenin içine kopyalanır. Ertesi gün ürün adı değişse eski sipariş eski adla kalır. Güncel kart her zaman Prisma’dadır. ### MeiliSearch İndeks ürün araması içindir; sipariş araması değildir. Saatlik tam yenileme üretimde Prisma’dan okuyup indeksi baştan kurar. Anlık güncelleme `product.upsert` / `product.deleted` olaylarıyladır. ## Katalog ve stok kartı \[Prisma] Ürünün tanımı burada, sipariş kalemi Mongo’dadır. Depodaki **miktar ve satış fiyatı** da bu gruptadır; giriş-çıkış hareketi Mongo’dadır. ### Vat ve Unit KDV: `name`, `rate` (Float). Birim: `name`, isteğe bağlı `shortName`, `symbol`, `multipler` (Float, varsayılan 1 — şemadaki yazım). ### Category Ağaç. `parentId` isteğe bağlı. `name`, `description`, `image`, `priority` (0), `isActive` (true), `deletedAt` soft delete. ### Product `code` benzersizdir. Üst ürün (`parentId`) varyant ağacı içindir. | Alan | Tip | Anlamı | | ------------- | -------------- | -------------- | | code | String, unique | Ürün kodu | | name | String | Ad | | descriptive | String? | Kısa tanım | | description | String? (Text) | Uzun açıklama | | priority | Int, 0 | Vitrin sırası | | vatId, unitId | Int | KDV ve birim | | isActive | Boolean, true | Satışta mı | | isHks | Boolean, true | HKS’ye tabi mi | | warnings | String? (Text) | Uyarı metni | Çocuk tablolar: görseller, kategoriler, favoriler, depo ürünleri, sepet, şirket tipi görünürlüğü, benzer adlar, HKS kodları, saklama koşulları, dış fiyat eşlemesi, ticker. ### ProductImage `url`, `priority` (0). ### ProductCategory `(productId, categoryId)` bileşik anahtar. ### ProductSimilarName Arama eş anlamlısı. `name`, `priority` (0), `isActive`. ### ProductHks | Alan | Tip | Anlamı | | ----------- | ------- | ------------- | | productCode | String? | HKS ürün kodu | | code | String | HKS kod | | name | String | HKS adı | ### ProductStorageCondition `key` = `StorageConditionType` (sıcaklık, nem, ışık, havalandırma, ambalaj, raf ömrü, diğer). `value` metin, `priority` 0. ### ProductCompanyType Hangi şirket tipinin ürünü göreceği. `(companyTypeId, productId)` tektir. `priority` isteğe bağlı. ### CompanyType `name`, isteğe bağlı `hksCode`. Alıcılar ve ürün görünürlüğü bağlanır. ### WarehouseProduct Depodaki ürün kartı. `(warehouseId, productId)` tektir. | Alan | Tip | Anlamı | | ------------- | ------------- | ---------------------- | | stock | Float, 0 | Güncel miktar | | criticalStock | Float, 0 | Kritik eşik | | minQuantity | Float, 1 | Asgari sipariş miktarı | | isActive | Boolean, true | Listeleniyor mu | ### WarehouseProductPrice Kademeli fiyat. `price`, `margin` (varsayılan 30), `currency` (`TRY`), `minQuantity`, `avarageCost` (0, ortalama maliyet), `discountPercentage` (0), `priceWithoutDiscount` (0). ### StockBalance `WarehouseProduct` ile 1:1. `amount` (Float, 0) ayrı bakiye miktarıdır; `stock` alanından farklı bir sayaç olarak durur. ### PriceSource Dış fiyat kaynağı. `key` benzersiz (mum belgesindeki `source` alanı). `adapter` çekici adı. `config` JSON. `isActive`. ### ExternalProductMapping `(sourceId, externalName)` tektir. `unit` isteğe bağlı. `productId` boşsa henüz eşlenmemiştir. ### ProductTickerStats Ürünle 1:1. `latestPrice`, `changePercent`, `volatilityRangePercent`. ### ProductFavorite `(userId, productId)` bileşik anahtar. `createdAt`. ### ProductBasket `(userId, productId)` benzersiz. `quantity` Float, `isActive` true. ### Post İçerik. `title`, `description`, `image`, `video`, `priority`, `isActive`, `type` (`SLIDER` / `BANNER` / `STORY` / `ACADEMY`), `userType` (hedef kitle), `link`, isteğe bağlı sahip, `publishedAt` / `unPublishedAt`, `deletedAt`. ## CRM ve alıcı grupları \[Prisma] Alıcının teslimat kartı, yönetici ilişkisi ve segmenti. ### BuyerAddress Alıcıya özel adres kartı. Fiziksel `Address` buraya bağlanır. | Alan | Tip | Anlamı | | -------------------- | ---------------------- | ---------------------- | | name | String | Kart adı | | buyerId | Int | Alıcı | | offHoursDelivery | Boolean? | Mesai dışı teslim | | openHour | Float?, 9 | Açılış saati | | closeHour | Float?, 18 | Kapanış saati | | isInvoice | Boolean, false | Fatura adresi mi | | taxNumber, taxOffice | String? | Vergi | | birthDate | DateTime? | E-belge / kimlik | | identityNumber | String? | TCKN | | isEFaturaTr | Boolean, false | E-fatura | | isMernisFallback | Boolean, false | MERNİS yedek | | officerNote | String? | Yetkili notu | | signageName | String?(255) | Tabela | | exteriorImage | String?(1024) | Dış foto | | problemType | AdminBuyerProblemType? | Eksik/hatalı veri tipi | | addressId | Int? | Fiziksel adres | | serviceAreaId | Int? | Dikdörtgen alan | | coordinateZoneId | Int? | Poligon bölge | | minBasketPrice | Float, 0 | Bu adrese özel asgari | Alıcının seçili teslimat / fatura işaretleri bu satıra 1:1 bakar (`selectedBy`, şemadaki `seletedInvoiceBy`). ### AdminBuyer Yönetici–alıcı CRM. `(adminId, buyerId)` tektir. | Alan | Tip | Anlamı | | --------------------------------------- | ----------------------- | ------------------------------------- | | fixServicePrice | Float, 0 | Sabit hizmet bedeli | | orderCount | Int?, 0 | Sipariş adedi | | orderPeriodDay | Int?, 0 | Sipariş periyodu (gün) | | riskOffLost | Boolean, false | Kayıp riski (şema yazımı) | | isOffilePayment | Boolean, false | Çevrimdışı ödeme (şema yazımı) | | deliveredOrderCount / Amount / LastDate | Int?/Float?/DateTime? | Teslim özeti | | returnedOrderCount / Amount / LastDate | | İade özeti | | issueOrderCount / LastDate | | Sorun özeti | | lastCallDate, callCount | DateTime? / Int? | Arama | | status | AdminBuyerStatus? | `ACTIVE`, `INACTIVE`, `ZOMBIE` | | actionStatus | AdminBuyerActionStatus? | Sonraki iş (arama, sipariş, ziyaret…) | | feadbackScore | Int?, 0 | Geri bildirim (şema yazımı) | ### AdminBuyerStatusHistory `status` + `createdAt`. Durum tarihçesi. ### AdminBuyerFeadbackHistory `feadbackScore` tarihçesi. ### AdminBuyerOfficer `(adminBuyerId, officerId)` tektir. Alıcıya yetkili ataması. ### AdminBuyerComment | Alan | Tip | Anlamı | | --------------- | --------------------------- | ---------------------------------------------------------------------------- | | createdByUserId | Int | Yazan kullanıcı | | comment | String | Metin | | type | AdminBuyerCommentType, INFO | Bilgi, uyarı, kritik, arama, sepet, kalite, fiyat, teslimat, destek, fatura… | | officerRole | OfficerRole? | Hangi ekip bağlamı | | isActive | Boolean, true | Aktif | ### BuyerGroup | Alan | Tip | Anlamı | | -------------------- | -------------- | --------------------------------------- | | code | String, unique | Kod | | name | String | Ad | | rank | Int, unique | Kademe; yüksek = üst grup (şema yorumu) | | minMonthlyRevenue | Float, 0 | Aylık ciro eşiği | | minMonthlyOrderCount | Int, 0 | Aylık sipariş eşiği | | minAvgBasketSize | Float, 0 | Ortalama sepet eşiği | | description | String? | Açıklama | | badgeColor | String? | Rozet rengi | | isActive | Boolean, true | Aktif | Üç eşik birlikte aranır. ### BuyerGroupEvaluation Ölçüm satırı. `(buyerId, evaluatedAt)` indeksi. | Alan | Tip | Anlamı | | ---------------------- | -------------- | --------------------------------------------------- | | previousGroupId | Int? | Önceki grup (kolon; ilişki `resultGroup` üzerinden) | | resultGroupId | Int? | Sonuç grup | | periodStart, periodEnd | DateTime | Dönem | | monthlyRevenue | Float | Ölçülen ciro | | monthlyOrderCount | Int | Ölçülen adet | | avgBasketSize | Float | Ölçülen sepet | | changed | Boolean, false | Grup değişti mi | | evaluatedAt | DateTime, now | Ölçüm anı | ## Prisma enum değerleri Kaynak yalnızca `schema.prisma`. Mongo / sipariş durumları [ayrı listededir](/data/mongodb/enums). ### UserType `ADMIN`, `OFFICER`, `BUYER`, `SELLER`, `SYSTEM` Hesap tipi. [Roller](/overview/roles). ### OfficerRole `MANAGER`, `MARKETING`, `WORKER`, `DRIVER`, `PURCHASING`, `PURCHASING_ASSISTANT`, `HEADOF_MARKETING`, `ADMIN_ASSISTANT`, `IT`, `IK` ### TokenProvider `FCM` — tek değer. ### PostType `SLIDER`, `BANNER`, `STORY`, `ACADEMY` ### Currency `TRY` — tek değer. Depo fiyat satırında kullanılır. ### AddressType `BUYER_ADDRESS`, `BUYER_SHOP_ADDRESS`, `WAREHOUSE_ADDRESS` ### AdminBuyerCommentType `INFO`, `WARNING`, `CRITICAL`, `CALL`, `BASKET_MIN_AMOUNT`, `PRODUCT_QUALITY`, `PRODUCT_PRICE`, `DELIVERY_TIME`, `DELIVERY_REQUEST`, `SUPPORT`, `INVOICE_ISSUE` ### StorageConditionType `TEMPERATURE`, `HUMIDITY`, `LIGHT`, `VENTILATION`, `PACKAGING`, `SHELF_LIFE`, `OTHER` ### PaymentPeriod Haftanın günü: `MONDAY` … `SUNDAY`. Satıcı ödeme günü. ### AdminBuyerStatus `ACTIVE`, `INACTIVE`, `ZOMBIE` ### AdminBuyerActionStatus `CALL_WAITING`, `CALL_BLOCKED`, `ORDER_WAITING`, `ORDER_CREATED`, `RIVAL_MISSING`, `SELF_MISSING`, `VISIT_WAITING`, `BUYER_CLOSED` ### AdminBuyerProblemType `BIRTH_DATE`, `TAX_NUMBER`, `TAX_OFFICE`, `IDENTITY_NUMBER`, `LOCATION_ISSUE`, `COMPANY_NAME_ISSUE`, `ADDRESS_ISSUE`, `ADDRESS_DESCRIPTION_ISSUE` Adres kartındaki eksik veya hatalı veri. ### SurveyQuestionType `SINGLE_CHOICE`, `MULTI_CHOICE`, `RATING`, `TEXT` ## Cari ve fatura numarası \[Prisma] Hareket defteri ve kesilmiş fatura belgesi Mongo’dadır. Burada **güncel bakiye**, **belge numarası sayacı** ve **anket soru tanımı** durur. ### FinancialAccount `(userId, warehouseId)` tektir. `warehouseId` boş olabilir (depo bağımsız hesap). Kayıt ödülü, tanımındaki `warehouseId` ile bu tabloyu upsert eder (hesap yoksa oluşturur, varsa bakiyeyi artırır). Ödül tanımının kendisi bu şemada yoktur; kod listesidir. [Kayıt ödülü](/flows/registration#kayıt-ödülü). | Alan | Tip | Anlamı | | ------------- | -------- | ------------------------------------------- | | balance | Float, 0 | Bakiye. Şema yorumu: artı alacak, eksi borç | | creditLimit | Float, 0 | Limit | | boxBalance | Int, 0 | Kasa / kasa adedi | | palletBalance | Int, 0 | Palet adedi | ### InvoiceSequence `(sequenceType, prefix, year)` tektir. `sequenceType` serbest string (ör. EINVOICE, EARCHIVE, RECEIPT). `prefix` belge öneki. `currentValue` son sayı. ### HksInvoiceTracker Künye arama sayacı. `lastSearchDate` (indeksli), isteğe bağlı `lastFoundDate`, `totalSearchCount` (0). ### SurveyQuestion Sipariş sonrası anketin **tanımı**. Cevaplar Mongo `orderSurveyResponses` koleksiyonundadır. | Alan | Tip | Anlamı | | ----------- | ------------------ | ------------------------------------------------- | | title | String | Soru | | description | String? | Açıklama | | type | SurveyQuestionType | `SINGLE_CHOICE`, `MULTI_CHOICE`, `RATING`, `TEXT` | | isActive | Boolean, true | Aktif | | deletedAt | DateTime? | Soft delete | ### SurveyChoice `(questionId, choiceId)` tektir. `label`, `order` (0). `(questionId, order)` indeksi vardır. ### SurveyScale Soruyla 1:1. `min`, `max`, isteğe bağlı `minLabel` / `maxLabel`. Defter ve fatura belgesi: [Cari ve fatura (Mongo)](/data/mongodb/finance-invoices). ## Coğrafya ve adres \[Prisma] Hiyerarşi: ülke → il → ilçe → mahalle. Adres ilçe ve mahalleye bağlanabilir. Alt kayıtlar üst silinince cascade ile gider (`City` ← `Country`, `District` ← `City`, `Neighborhood` ← `District`). Adresteki ilçe/mahalle silinirse bağlantı `SetNull` olur. ### Country | Alan | Tip | Anlamı | | --------- | ------------- | ---------------- | | flag | String | Bayrak | | name | String | Ad | | phoneCode | String(5) | Uluslararası kod | | isActive | Boolean, true | Aktiflik | | hksCode | String? | HKS ülke kodu | ### City | Alan | Tip | Anlamı | | --------- | ------------- | -------- | | name | String | İl adı | | hksCode | String? | HKS | | isActive | Boolean, true | Aktiflik | | priority | Int, 0 | Sıra | | countryId | Int | Ülke | ### District ve Neighborhood İlçe ve mahalle: `name`, `isActive` (true), isteğe bağlı `hksCode`, üst kimlik (`cityId` / `districtId`). ### Address Fiziksel yer. Tip `AddressType`: `BUYER_ADDRESS`, `BUYER_SHOP_ADDRESS`, `WAREHOUSE_ADDRESS`. | Alan | Tip | Anlamı | | --------------------------------------- | ----------- | -------------- | | type | AddressType | Ne için | | address | String | Açık adres | | building, flatNumber, doorNumber, floor | String? | Bina ayrıntısı | | districtId, neighborhoodId | Int? | İdari bağ | | latitude, longitude | Float? | Koordinat | | updatedAt | DateTime | Güncelleme | Aynı adres kaydına alıcı, alıcı adresi, depo ve satıcı bağlanabilir. Alıcının **teslimat kartı** bu tablonun üstünde duran `BuyerAddress` modelidir — vergi, saat, bölge ve asgari sepet oradadır. [CRM](/data/prisma/crm). ## Kimlik ve izinler \[Prisma] Hesabın kendisi ve ona bağlı doğrulama / cihaz / izin kayıtları. ### PhoneVerification Telefon doğrulama kodu. | Alan | Tip | Anlamı | | -------------------- | ------------- | --------------- | | id | Int, otomatik | Kimlik | | countryId | Int | Ülke | | phone | String(20) | Numara | | code | String(30) | Doğrulama kodu | | createdAt, updatedAt | DateTime | Zaman damgaları | ### EmailVerification E-posta doğrulama. `email` benzersizdir. | Alan | Tip | Anlamı | | -------------------- | -------------- | ------- | | id | Int | Kimlik | | email | String, unique | E-posta | | code | String | Kod | | createdAt, updatedAt | DateTime | Zaman | ### User Tüm rollerin ortak hesabı. Telefon ve e-posta ayrı ayrı benzersizdir. Silme `deletedAt` ile yumuşaktır. | Alan | Tip | Anlamı | | -------------------- | ----------------- | ----------------------------------------------- | | id | Int | Kimlik | | type | UserType | `ADMIN`, `OFFICER`, `BUYER`, `SELLER`, `SYSTEM` | | avatar | String? | Görsel URL | | firstName, lastName | String? | Ad soyad | | countryId | Int | Ülke | | phone | String?, unique | Telefon | | email | String?, unique | E-posta | | password | String? | Parola özeti | | unreadMessageCount | Int, varsayılan 0 | Okunmamış sohbet | | refreshToken | String? | Yenileme jetonu özeti | | firebaseUUID | String? | Firebase kullanıcı id | | paytrUtoken | String? | PayTR saklı kart kullanıcı jetonu | | deletedAt | DateTime? | Soft delete | | lastSeen | DateTime, now | Son görülme | | createdAt, updatedAt | DateTime | Zaman | 1:1 profiller: `buyer`, `seller`, `admin`, `officer`. 1\:n: cihaz, izin, favori, sepet, finansal hesap, yazdığı CRM notları, sahip olduğu postlar. ### Permission ve UserPermission İzin tanımı `code` ile tektir (ör. `admin:buyer:full`). `userType` varsayılanı `OFFICER`. Kullanıcı ataması `(userId, permissionId)` çiftinde tektir; silmede cascade. ### UserDevice Push kaydı. `(userId, deviceId)` tektir. | Alan | Tip | Anlamı | | ------------- | ------------- | ------------- | | deviceName | String | Görünen ad | | deviceId | String | Cihaz kimliği | | token | String | FCM jetonu | | tokenProvider | TokenProvider | Yalnız `FCM` | ### Admin Yönetici profili. `userId` tektir. `callService` arama entegrasyonu kimliğidir. Depolar ve `AdminBuyer` kayıtları buradan iner. ### Officer Yetkili profili. `userId` tektir. `latitude` / `longitude` anlık konum. `role` isteğe bağlı `OfficerRole`. Depo ataması `AdminOfficer`, alıcı ataması `AdminBuyerOfficer`. ### Seller Tedarikçi. `userId` isteğe bağlı ve benzersizdir (kullanıcısız satıcı olabilir). | Alan | Tip | Anlamı | | -------------------- | -------------------------------- | ----------------- | | name | String | Unvan | | description, phone | String? | Açıklama, telefon | | taxNumber, taxOffice | String? | Vergi | | typeId | Int? | SellerType | | addressId | Int? | Adres | | paymentPeriod | PaymentPeriod, varsayılan MONDAY | Ödeme günü | ### SellerType Yalnız `id` ve `name`. Satıcıları gruplar. ### Buyer Alıcı profili. `userId` tektir. | Alan | Tip | Anlamı | | ------------------------ | -------------- | ------------------------------ | | name, description, logo | String? | İşletme kartı | | companyTypeId | Int? | Şirket tipi (ürün görünürlüğü) | | email | String? | İletişim e-postası | | referenceCode | String? | Referans kodu | | isOfflinePayment | Boolean, false | Kapı / çevrimdışı ödeme izni | | selectedAddressId | Int?, unique | Seçili teslimat adresi | | selectedInvoiceAddressId | Int?, unique | Seçili fatura adresi | | waitingSurveyOrderId | String? | Anket bekleyen sipariş id | | currentGroupId | Int? | Alıcı grubu | | groupAssignedAt | DateTime? | Gruba alınma zamanı | | addressId | Int? | Eski/bağlı Address | Adres ve CRM detayı: [CRM ve alıcı grupları](/data/prisma/crm). ## Prisma genel bakış \[İlişkisel kartlar] Kaynak: `prisma/schema.prisma`. Veritabanı MySQL. 57 model, 13 enum. Tablo adı = model adı. Bu sayfa **hangi tablonun hangi işe yaradığını** gösterir. Alan listeleri alt sayfalardadır. ### Alan tipleri nasıl okunur? Prisma tipi, MySQL’deki karşılığa yakındır: | Prisma | Anlamı | | ---------- | ------------------------------------------------------------- | | `Int` | Tam sayı, çoğu tabloda otomatik artan kimlik | | `Float` | Ondalık (fiyat, stok, koordinat, saat) | | `String` | Metin; bazen uzunluk sınırlı (telefon 20, adres görseli 1024) | | `Boolean` | Evet/hayır | | `DateTime` | Zaman. `now()` varsayılanı ve `@updatedAt` sık kullanılır | | `Json` | Serbest yapı (poligon noktaları, fiyat kaynağı config) | | Enum | Sabit değer listesi — [Prisma enum’ları](/data/prisma/enums) | `?` işaretli alan boş olabilir. İlişki alanları gerçek kolondan çok Prisma’nın bağlarıdır; tabloda duran genellikle `*Id` kolonudur. ### Model grupları | Grup | Modeller | Sayfa | | ------------------ | ---------------------------------------------------------------------------------- | -------------------------------------------------------- | | Doğrulama ve hesap | PhoneVerification, EmailVerification, User, UserDevice, Permission, UserPermission | [Kimlik](/data/prisma/identity) | | Yer | Country, City, District, Neighborhood, Address | [Coğrafya](/data/prisma/geography) | | Profiller | Admin, Officer, Seller, SellerType, Buyer, CompanyType | [Kimlik](/data/prisma/identity), [CRM](/data/prisma/crm) | | CRM | AdminBuyer ve tarihçe/not/yetkili, BuyerAddress, BuyerGroup, BuyerGroupEvaluation | [CRM](/data/prisma/crm) | | Depo | Warehouse, hizmet alanı, bölge, gün fiyatı, ayar, araç, AdminOfficer | [Depo](/data/prisma/warehouse) | | Katalog | Category, Product ve görsel/isim/HKS/saklama, Vat, Unit | [Katalog](/data/prisma/catalog) | | Stok kartı | WarehouseProduct, WarehouseProductPrice, StockBalance | [Katalog](/data/prisma/catalog) | | Fiyat dış kaynak | PriceSource, ExternalProductMapping, ProductTickerStats | [Katalog](/data/prisma/catalog) | | Sepet / içerik | ProductBasket, ProductFavorite, Post | [Katalog](/data/prisma/catalog) | | Cari / fatura no | FinancialAccount, InvoiceSequence, HksInvoiceTracker | [Cari](/data/prisma/finance) | | Anket tanımı | SurveyQuestion, SurveyChoice, SurveyScale | [Cari](/data/prisma/finance) | ### Bilinçli yazım Şemada bazı alan adları kod tabanındaki yazımıyla durur (düzeltilmemiştir): `multipler`, `avarageCost`, `feadbackScore`, `isOffilePayment`, `seletedInvoiceBy`, `riskOffLost`. Belgelerde alan **koddaki adıyla** yazılır; yanında düzgün Türkçe anlamı verilir. ## Depo ve teslimat alanı \[Prisma] Depo hem stok yeri hem teslimat merkezidir. Alıcının adresi bir dikdörtgen alana veya poligon bölgeye düşer; asgari sepet oradan gelir. ### Warehouse | Alan | Tip | Anlamı | | --------- | ------- | ------------------- | | name | String | Depo adı | | hksCode | String? | HKS şube / yer kodu | | email | String? | İletişim | | adminId | Int | Yönetici | | addressId | Int? | Fiziksel adres | Bağlı: hizmet alanları, koordinat bölgeleri, yetkililer, ürünler, araçlar, ayarlar, cari hesaplar. ### WarehouseServiceArea Dikdörtgen kutu. | Alan | Tip | Anlamı | | ------------------------------ | ------------- | ------------ | | name | String? | Ad | | minLat, maxLat, minLng, maxLng | Float | Sınırlar | | minBasketPrice | Float, 0 | Asgari sepet | | isActive | Boolean, true | Aktif | ### WarehouseCoordinateZone Poligon. | Alan | Tip | Anlamı | | -------------- | ------------- | --------------------- | | name | String | Ad | | minBasketPrice | Float | Varsayılan asgari | | points | Json | Köşe noktaları | | isActive | Boolean, true | Aktif | | unlockedUntil | DateTime? | Geçici kilitsiz bitiş | ### WarehouseCoordinateZoneDayPrice `(zoneId, dayOfWeek)` tektir. `dayOfWeek` tam sayı (haftanın günü). `minBasketPrice` o güne özel asgari. ### WarehouseSetting `(warehouseId, key)` tektir. `value` uzun metin. Kodda bilinen anahtar: `AI_NOTIFICATION_PROMPT`. ### WarehouseVehicle | Alan | Tip | Anlamı | | ----------- | ------------- | ---------------- | | name | String | Ad | | plateNumber | String | Plaka | | model | String | Model | | kilometer | Float | Km | | volume | Float | Hacim kapasitesi | | isActive | Boolean, true | Aktif | ### AdminOfficer Depo–yetkili ataması. `(warehouseId, officerId)` tektir. Hareket ve sefer belgeleri MySQL’de değildir: [Stok ve transfer](/data/mongodb/stock-transfers). ## İletişim ve iş akışı \[MongoDB] ### Conversation (`conversations`) | Alan | Anlamı | | --------------- | -------------------------------------------------------- | | users\[] | Katılımcı kopyaları (okunmamış sayısı, lastReadAt dahil) | | name | Konuşma adı | | startDate | Başlangıç | | createdByUserId | Açan | | adminUserIds | Yönetenler | | contextType | RETURN, SUPPORT, ORDER, TEAM, PRODUCT | | contextId | Bağlam kaydı | | lastMessage | Son mesaj özeti | | unreadCounts | Okunmamış | ### Message (`messages`) | Alan | Anlamı | | -------------------- | ------------------------------------------ | | conversationId | Konuşma | | senderUserId | Gönderen | | message | Metin | | images, video, voice | Ek | | type | PROBLEM, REQUEST, SUGGESTION, ANNOUNCEMENT | | status | Tipe göre durum makinesi (duyuruda yok) | | quote, forward | Alıntı / iletme | | editedAt, deletedAt | Düzen / sil | Sorun: `OPEN`, `IN_PROGRESS`, `RESOLVED`, `CLOSED`. İstek: `PENDING`, `IN_PROGRESS`, `COMPLETED`, `REJECTED`. Öneri: `PENDING`, `UNDER_REVIEW`, `ACCEPTED`, `REJECTED`. ### Notification (`notifications`) `userId`, `title`, `message`, `isRead`, `data` (serbest), zaman damgaları. ### Department (`departments`) Depo kanban kökü. `name`, `warehouseId`, `cards[]`. Kart: `name`, `color`, `index`, `tasks[]`. Görev: oluşturan, atananlar, `index`, `color`, `title`, `description`, `dueDate`, `completedAt`, `hiddenAt`, `notes[]`, `history[]`, `images[]`. Not: `userId`, `userName`, `text`. Geçmiş: `userId`, `key`, `value`. ### UserLog (`userLogs`) `userId`, `deviceType`, `deviceName`, `code`, `message`, `logType`, zaman damgaları. ## MongoDB durum değerleri Bu değerler Prisma şemasında değil, TypeScript sabitlerindedir. Sipariş belgesi ve birçok Mongo alanı bunları kullanır. ### Sipariş ve teslimat **BuyerOrderStatus:** `PAYMENT_WAITING`, `PAYMENT_FAILED`, `PAYMENT_TIMEOUT`, `PENDING`, `APPROVED`, `IN_PROGRESS`, `CANCELLED`, `RETURNED`, `READY`, `SHIPPED`, `DELIVERED`, `RETURN_PENDING`, `RETURN_APPROVED`, `RETURN_IN_PROGRESS`, `RETURN_REJECTED` Son dört kalem, açık iade talebinin kalem durumudur. **DeliveryType:** `CUSTOMER`, `COURIER` **BuyerOrderHistoryAction:** `APPROVED`, `PREPARING`, `READY`, `SHIPPED`, `DELIVERED`, `RETURNED`, `CANCELED`, `PAID`, `PAYMENT_FAILED`, `PAYMENT_TIMEOUT` ### İade **ReturnRequestStatus:** `PENDING`, `APPROVED`, `REJECTED`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED` **ReturnReason:** `ROTTEN`, `DEFORMED`, `LOW_QUALITY`, `DIFFERENT`, `EXCESS` **ReturnMediaType:** `IMAGE`, `VIDEO` Yönetici bekleyenden onay/red/iptale; yetkili onaylıdan işleme ve tamamlamaya geçebilir. Tam geçiş tablosu `order-return.const.ts` içindedir. ### Sorun **BuyerOrderIssueStatus:** `OPEN`, `SEEN`, `RESOLVED` **BuyerOrderIssueType:** `DELIVERY_TIME`, `DELIVERY_TYPE`, `PRODUCT_QUALITY`, `INVOICE_ISSUE`, `OTHER` **BuyerOrderProductProblemType:** `DAMAGED`, `MISSING`, `BROKEN`, `WRONG`, `OTHER` ### Ödeme **PaymentPlatform:** `MAGICPAY`, `PAYTR`, `PAYWALL`, `MANUAL` — varsayılan sabit `PAYWALL` **PaymentStatus:** `PENDING`, `SUCCESS`, `FAIL` **PurchasePaymentType:** `ONLINE`, `OFFLINE` **PurchasePaymentMethod:** `CASH`, `CARD`, `TRANSFER`, `CHECK`, `ACCOUNT` **PaymentLineType:** `SUM`, `SUBTRACT` ### Transfer **TransferProvider:** `PLATFORM` **TransferStatus:** `PENDING`, `SHIPPING`, `DELIVERED`, `CANCELLED`, `RETURNED` **VehicleInvoiceStatus:** `PENDING`, `PROCESSING`, `COMPLETED`, `PARTIAL` ### Stok **StockEntryStatus:** `PRE_DECLARED`, `DECLARED`, `CONFIRMED`, `CANCELLED` **StockExitType:** `SALE`, `FIRE`, `ADJUSTMENT` **StockExitReason:** `DAMAGE`, `EXPIRED`, `LOST`, `OPERATION`, `OTHER`, `COUNT_SHORTAGE` **WarehouseProductStockInType:** `DRAFT`, `PURCHASE`, `SELL_RETURN`, `SELL_CANCEL`, `CANCEL_DRAFT` **WarehouseProductStockOutType:** `SELL_ONLINE`, `SELL_OFFLINE`, `OUTAGE`, `ADJUSTMENT` **WarehouseProductStockOutReason:** `DAMAGE`, `EXPIRED`, `LOST`, `RETURN`, `OPERATION`, `OTHER` ### Fatura **InvoiceStatus:** `DRAFT`, `SENT`, `APPROVED`, `REJECTED`, `CANCELLED`, `PAID` **InvoiceType:** `E_INVOICE`, `E_ARCHIVE`, `RECEIPT` **InvoiceProvider:** `IZIBIZ` **InvoiceReferenceType:** `ORDER`, `PAYMENT`, `TRANSACTION`, `MANUAL` **InvoiceLineReferenceType:** `ORDER` ### Mesaj ve talep **ConversationContextType:** `RETURN`, `SUPPORT`, `ORDER`, `TEAM`, `PRODUCT` **MessageType:** `PROBLEM`, `REQUEST`, `SUGGESTION`, `ANNOUNCEMENT` **ProductRequestStatus:** `PENDING`, `REVIEWED` **ProcurementRequestStatus:** `PENDING`, `APPROVED`, `CANCELLED`, `IN_PROGRESS`, `COMPLETED` Cari hareket tipleri alan listesiyle birlikte: [Cari ve fatura](/data/mongodb/finance-invoices). Prisma enum’ları: [Prisma enum’ları](/data/prisma/enums). ## Cari ve fatura \[MongoDB] Bakiye Prisma’dadır. Bu koleksiyonlar **işlem ve belge**dir. ### Payment (`payments`) Koleksiyon adı şemada açık verilmemiştir; Mongoose varsayılanı `payments`. | Alan | Tip | Anlamı | | ---------------------- | -------------------------------------- | ---------------------------------------- | | userId | number | Prisma kullanıcı | | platform | PaymentPlatform, değişmez | `PAYTR`, `PAYWALL`, `MAGICPAY`, `MANUAL` | | paymentMethod | PurchasePaymentMethod, varsayılan CARD | Yöntem | | transactionId | string, null | Sağlayıcı işlem no | | orderId | string, zorunlu, değişmez | Sipariş id | | status | PaymentStatus | `PENDING`, `SUCCESS`, `FAIL` | | amount | number, zorunlu, değişmez | Tutar | | failedReasonCode / Msg | string, null | Hata | ### AccountTransaction (`accountTransactions`) Birçok alan yazıldıktan sonra değişmez (immutable): depo, kullanıcı, tip, tutar, bakiye, açıklama. | Alan | Tip | Anlamı | | --------------------------- | ---------------------- | ----------------------------------------------------- | | warehouse | WarehouseCopy, zorunlu | Depo | | user | UserCopy | Hesap sahibi | | transactionType | TransactionType | Hareket tipi | | transactionTypeLabel | sanal | Türkçe etiket | | transactionTypeCode | string, null | Ek kod | | amount | number | Artı alacak, eksi borç | | balance | number | Bu işlemden **sonraki** bakiye | | description | string? | Açıklama | | referenceId / referenceType | string? | ORDER, PAYMENT vb. | | invoiceNumber | string? | Belge no | | dueDate | Date? | Vade | | isClosed | boolean, false | Kapandı mı | | transactionStatus | TransactionStatus | COMPLETED / PENDING / APPROVED / REJECTED / CANCELLED | | transactionStatusLabel | sanal | Türkçe | | createdByUser | UserCopy | Oluşturan | | approvedAt | Date? | Onay | Hareket tipi etiketleri koddaki Türkçe sözlükten: | Tip | Etiket | Bakiye yönü | | ------------------------------------------------------------------- | -------------------------------------- | ----------- | | TRANSFER | Hesaplar arası transfer | her iki | | BANK\_TRANSFER | Banka hesabına transfer | eksi | | REWARD | Ödül | artı | | COMPENSATION | Telafi | artı | | SHORT\_SUPPLY\_OF\_PRODUCT | Eksik ürün tedariği | artı | | CORRECTION | Düzeltme | her iki | | EXCESS\_PRODUCT\_SUPPLY | Fazla ürün tedariği | artı | | DEFECTIVE\_PRODUCT\_COMPENSATION | Kusurlu ürün telafisi | artı | | DEDUCTION | Bakiyeden düşüm | eksi | | USE\_BALANCE\_FOR\_PURCHASE | Alışverişte bakiye kullanımı | eksi | | PAYMENT\_BALANCE | Borç ödemesi | artı | | REFUND\_BALANCE\_FOR\_ORDER | Sipariş iptali bakiye iadesi | her iki | | TRANSFER\_TO\_BALANCE\_FOR\_ORDER | Sipariş iptali cariye aktarım | artı | | REFUND\_FALLBACK\_TO\_BALANCE\_FOR\_ORDER | Kart iadesi başarısız — cariye aktarım | artı | | ORDER\_AMOUNT\_DIFFERENCE (`TRANSFER_BALANCE_FOR_ORDER_DIFFERENCE`) | Sipariş tutar farkı | her iki | | OFFLINE\_PURCHASE\_FOR\_ORDER | Kapıda ödemeli sipariş | eksi | | OFFLINE\_PAYMENT\_FOR\_ORDER | Kapıda ödeme tahsilatı | artı | | STOCK\_PURCHASE | Satıcıdan ürün tedariği | artı | | STOCK\_RETURN | Satıcıya ürün iadesi | eksi | | STOCK\_PURCHASE\_PAYMENT | Stok alımı peşin ödeme | eksi | Elle girilebilen çekirdek tipler: transfer, ödül, telafi, düşüm. Daha geniş manuel seçenek listesi koddaki `MANUAL_TRANSACTION_TYPE_OPTIONS` dizisindedir. `REWARD` ayrıca yeni alıcı kaydında otomatik üretilir. O zaman `description` ödül adı, `transactionTypeCode` ödül `id` değeridir (ör. `BUYER_SIGNUP_REWARD_2026_08`). Tanım listesi Prisma’da değil, `financial` sabitlerindedir. [Kayıt ödülü](/flows/registration#kayıt-ödülü). ### Invoice (`invoices`) Giden belge. Kullanıcı, depo, tutarlar ve tarih çoğu alanda değişmez. | Alan | Anlamı | | --------------------------------- | ------------------------------------------------ | | documentNo | Belge no | | user | Faturanın kesildiği kullanıcı kopyası | | warehouse | İsteğe bağlı depo | | totalAmount, taxAmount, netAmount | Tutarlar (net = vergi hariç, şema yorumu) | | currency | Varsayılan `TRY` | | invoiceDate | Tarih | | status | DRAFT, SENT, APPROVED, REJECTED, CANCELLED, PAID | | invoiceProvider | Yalnız `IZIBIZ` | | invoiceProviderId / Raw | Sağlayıcı id ve ham yanıt | | invoiceLineReferences | Satır tipi ORDER ve referans id | ### PlatformInvoice (`platformInvoices`) Gelen tedarikçi e-belgesi: UUID, satıcı, depo, belge no, düzenleme/teslim tarihi, gönderen/alıcı VKN-unvan-alias, tutar, durum, `stockProcessed`, `stockNotApplicable`, `rawUbl`. ## MongoDB genel bakış \[Belgeler] Sipariş, tahsilat, stok hareketi ve rapor **belge** olarak durur. Prisma kartları belgenin içine kopya olarak gömülür; kopyalar ayrı koleksiyon değildir. ### Koleksiyonlar | Koleksiyon | İş | Sayfa | | ------------------------------------------------------------------------- | ------------------------ | ------------------------------------------------ | | `buyerOrders` | Alıcı siparişi | [Sipariş](/data/mongodb/orders) | | `buyerOrderReturns` | İade talebi | [Sipariş](/data/mongodb/orders) | | `returnMediaUploads` | Geçici iade medyası | [Sipariş](/data/mongodb/orders) | | `buyerOrderIssues` | Teslimat / kalite sorunu | [Sipariş](/data/mongodb/orders) | | `orderSurveyResponses` | Anket cevabı | [Sipariş](/data/mongodb/orders) | | `orderHeatmaps` | Sipariş yoğunluk hücresi | [Sipariş](/data/mongodb/orders) | | `ordernoteaisettings` | Sipariş notu AI ayarı | [Sipariş](/data/mongodb/orders) | | `payments` | Sağlayıcı ödeme işlemi | [Cari ve fatura](/data/mongodb/finance-invoices) | | `accountTransactions` | Cari defter | [Cari ve fatura](/data/mongodb/finance-invoices) | | `invoices` | Giden e-belge | [Cari ve fatura](/data/mongodb/finance-invoices) | | `platformInvoices` | Gelen tedarikçi belgesi | [Cari ve fatura](/data/mongodb/finance-invoices) | | `warehouseProductStockIn` / `Out` | Eski stok hareketi | [Stok](/data/mongodb/stock-transfers) | | `stockEntries` / `stockExits` | FIFO stok | [Stok](/data/mongodb/stock-transfers) | | `buyerOrderTransfers` | Kurye teslimatı | [Stok](/data/mongodb/stock-transfers) | | `warehouseVehicleTransfers` | Araç seferi | [Stok](/data/mongodb/stock-transfers) | | `warehouseVehicleLocations` | GPS noktası | [Stok](/data/mongodb/stock-transfers) | | `warehouseHeatmaps` / `warehouseReports` / `warehouseProductPriceHistory` | Depo özetleri | [Raporlar](/data/mongodb/reports) | | `conversations` / `messages` | Sohbet | [İletişim](/data/mongodb/communication) | | `notifications` | Bildirim kutusu | [İletişim](/data/mongodb/communication) | | `departments` | Kanban | [İletişim](/data/mongodb/communication) | | `productRequests` | Ürün talebi | [Sipariş](/data/mongodb/orders) | | `procurementRequests` | Satıcı tedarik talebi | [Stok](/data/mongodb/stock-transfers) | | `userLogs` | İstemci logu | [İletişim](/data/mongodb/communication) | | `productSalesReports` ve diğer raporlar | Günlük özet | [Raporlar](/data/mongodb/reports) | | `productPriceCandle` / `externalPriceRawSample` | Fiyat zaman serisi | [Raporlar](/data/mongodb/reports) | ### Gömülü kopyalar Ayrı koleksiyon değildir. Sipariş ve hareket belgelerinin içine yazılır: kullanıcı, alıcı, adres, depo, ürün, birim, KDV, yetkili, satıcı, araç. Anlamı: belgenin yazıldığı andaki kart fotoğrafı. [Nerede ne tutulur](/data/storage). ### Kimlik tipi Mongo belgelerinin `_id` değeri ObjectId’dir. Prisma kartlarının `id` değeri tam sayıdır. Sipariş `code` alanı insan okur (üretim `S` + sayı + `B` + alıcı id biçimindedir). Prisma `waitingSurveyOrderId` string tutar çünkü sipariş id’si Mongo’dadır. ## Sipariş ve iade \[MongoDB] Asıl sipariş gerçeği `buyerOrders` koleksiyonudur. Durum makinesi: [Alışveriş](/flows/shopping). ### BuyerOrder (`buyerOrders`) | Alan | Tip | Anlamı | | -------------------- | ------------------------------------ | ----------------------- | | code | string, zorunlu | İnsan okur kod | | number | number, zorunlu | Sıra no | | buyer | BuyerCopy | Alıcı anlık kopyası | | buyerAddress | BuyerAddressCopy | Teslimat adresi kopyası | | buyerInvoiceAddress | BuyerAddressCopy | Fatura adresi kopyası | | note | string | Alıcı notu | | status | BuyerOrderStatus, varsayılan PENDING | Sipariş durumu | | products | BuyerOrderProduct\[] | Kalemler | | preparedImages | string\[] | Hazırlık fotoğrafları | | purchase | PurchasePayment | Ödeme kırılımı | | delivery | BuyerOrderDelivery | Teslimat planı | | warehouse | WarehouseCopy | Depo kopyası | | pickerOfficer | OfficerCopy | Toplayan yetkili | | transfers | ObjectId\[] → BuyerOrderTransfer | Teslimat kayıtları | | history | BuyerOrderHistory\[] | Durum geçmişi | | invoice | BuyerOrderInvoice | Kesilmiş belge özeti | | officerNotes | BuyerOrderOfficerNote\[] | İç not | | pallet | number, 0 | Palet | | lastCancelDate | Date | Son iptal | | lastReturnDate | Date | Son iade | | buyerOfficers | OfficerCopy\[] | İlgili yetkililer | | createdAt, updatedAt | Date | Zaman damgaları | #### Kalem (BuyerOrderProduct) | Alan | Tip | Anlamı | | -------------------------------- | ---------------- | --------------------------------------------------- | | number | number | Kalem no | | productId | number | Prisma ürün id | | categoryIds | number\[] | Kategoriler | | code, name, image, warnings | string | Anlık ürün bilgisi | | status | BuyerOrderStatus | Kalem durumu (iade alt durumları dahil) | | quantity | number | Sipariş miktarı | | deliveryQuantity | number, 0 | Teslim miktarı | | vat, unit | kopya | KDV ve birim | | unitAmount | number | miktar × birim çarpanı (toplam kg, şema açıklaması) | | tareWeight | number, 0 | Dara | | box | number, 0 | Kasa | | price | ProductPriceCopy | Fiyat kademesi kopyası | | vatAmount, totalAmount | number | İlk tutarlar | | finalVatAmount, finalTotalAmount | number | Hazırlık sonrası tutarlar | | isHks | boolean | HKS kalemi | | transfer | ObjectId | Bu kalemin kurye kaydı | | warehouseProduct | kopya | Depo ürün kartı | | stockInReferences | dizi | Eski stok giriş id + miktar | | stockOutReference | ObjectId | Eski stok çıkış (değişmez) | | stockEntryReferences | dizi | FIFO lot id + miktar | | stockExitReference | ObjectId | FIFO çıkış (değişmez) | | hksNotifications | dizi | HKS ham yanıt, hatalar, zaman | #### Teslimat bloğu `deliveryType` (`CUSTOMER` / `COURIER`), `deliveryDate`, adres, `transferProvider` (`PLATFORM`), `distanceKm`, `carryInside`, `carryInsideFee`. #### Ödeme bloğu (purchase) Siparişe gömülüdür, ayrı koleksiyon değildir. Yöntem, çevrimiçi/çevrimdışı, sağlayıcı, tahsil/iade tutarı, `payments` referansı, ödeme tarihi, `isPaid`, tahsil eden, kargo, taksit, cari kullanımı, sabit hizmet, içeride taşıma, ürün/indirim/KDV/net toplam, para birimi, satır listeleri, havale bildirimi. Havale alt nesnesi: bildirim zamanı, not, banka, IBAN, dekont, onay zamanı ve onaylayan, hatırlatma zamanı. #### Geçmiş ve fatura özeti Geçmiş `action` değerleri: onay, hazırlık, hazır, sevk, teslim, iade, iptal, ödendi, ödeme başarısız, zaman aşımı. Fatura özeti: belge no, UUID, tarih, profil, tip, tutar, vergi. ### İade (`buyerOrderReturns`) | Alan | Anlamı | | -------------------------------------------- | ------------------- | | code | İade kodu | | buyerOrder / buyerOrderCode | Sipariş bağları | | buyer, warehouseId, warehouse | Kim ve nereden | | description | Açıklama | | status | ReturnRequestStatus | | items\[] | Kalem, neden, medya | | approvedBy, adminNote | Yönetici | | officerInstruction, processedBy, officerNote | Yetkili | | history, conversationId | İz ve sohbet | Nedenler: `ROTTEN`, `DEFORMED`, `LOW_QUALITY`, `DIFFERENT`, `EXCESS`. Kalem başına en fazla 3 medya. `returnMediaUploads` geçici yüklemedir (`userId`, `buyerOrderId`, `url`). ### Sorun (`buyerOrderIssues`) `status`: `OPEN`, `SEEN`, `RESOLVED`. `type`: teslimat zamanı/tipi, kalite, fatura, diğer. Kalem problem tipi: hasarlı, eksik, kırık, yanlış, diğer. ### Anket (`orderSurveyResponses`) `buyerOrderId`, `buyerId`, `responses[]`. Soru şablonu Prisma’dadır; cevabın içine soru kopyası da gömülebilir. ### Ürün talebi (`productRequests`) `buyer`, isteğe bağlı ürün, `productName`, `note`, `amount`, `status` (`PENDING` / `REVIEWED`). ### Heatmap ve AI ayarı `orderHeatmaps` hücre özetidir. `ordernoteaisettings` yönetici talimatı ve güncelleyen id tutar. ## Raporlar ve fiyat \[MongoDB] Bunlar operasyon belgesi değil, **türetilmiş özet**tir. Kaynak sipariş / stok / cari değişince yeniden kurulurlar. [Raporlama akışı](/flows/reporting). ### ProductSalesReport (`productSalesReports`) `warehouseId`, `date`, ürün satırları, toplamlar, `lastUpdated`, `updateCount`. ### ProductPurchaseReport (`productPurchaseReports`) Aynı gün/depo kalıbı; alım ve maliyet satırları. ### BuyerReport (`buyerReports`) Alıcı aktivite özeti. ### BuyerLifecycleReport (`buyerLifecycleReports`) Yaşam döngüsü ve ödeme kırılımları. ### FinancialAccountReport (`financialAccountReports`) Yetkili, neden ve kullanıcı tipi grupları, toplamlar. `BalanceDefinitionSource` enum’u rapor şemasındadır. ### WarehouseReport (`warehouseReports`) Ürün, kategori, alıcı, tedarikçi, iade/sorun, teslimat istatistikleri; tarih ve depo anahtarı. ### WarehouseHeatmap (`warehouseHeatmaps`) Coğrafi hücre. Periyot enum’u `WarehouseHeatmapPeriod`. ### WarehouseProductPriceHistory (`warehouseProductPriceHistory`) `warehouseProductId`, fiyat anlık görüntü dizisi. ### ProductPriceCandle (`productPriceCandle`) OHLC mum: ürün, depo, zaman aralığı, açık/yüksek/düşük/kapanış. ### ExternalPriceRawSample (`externalPriceRawSample`) Dış piyasadan ham örnek (kaynak, eşleme, ham fiyat). Prisma `PriceSource.key` bu belgedeki kaynak alanına yazılır (şema yorumu). ## Stok ve transfer \[MongoDB] Miktarın **kartı** Prisma `WarehouseProduct.stock` alanındadır. Bu sayfa **hareket** belgeleridir. ### Eski stok girişi (`warehouseProductStockIn`) | Alan | Anlamı | | ------------------------------ | --------------------------- | | createdBy | İşlemi yapan kopya | | warehouse, warehouseProduct | Depo ve kart kopyası | | code | Belge kodu | | hksRaw | HKS ham künye | | type | WarehouseProductStockInType | | stockQuantity, stockUnitAmount | Miktar | | unitPrice, invoiceUnitPrice | Birim fiyat / fatura birim | | totalPrice, invoiceTotalPrice | Toplamlar | | seller | Satıcı kopyası | | comments, stars, imageUrls | Kalite ve görsel | | invoiceId | Bağlı fatura | | remainingAmount | Kalan | | fallbackUsages | Yedek tüketim | Tipler: `DRAFT`, `PURCHASE`, `SELL_RETURN`, `SELL_CANCEL`, `CANCEL_DRAFT`. Taslak değilse Prisma stok artar. ### Eski stok çıkışı (`warehouseProductStockOut`) Tip: `SELL_ONLINE`, `SELL_OFFLINE`, `OUTAGE`, `ADJUSTMENT`. Neden: hasar, SKT, kayıp, iade, operasyon, diğer. Sipariş referansı, maliyet, kâr, stok-in referansları. ### FIFO giriş (`stockEntries`) | Alan | Anlamı | | --------------------------------------- | ---------------------------------------------------- | | status | `PRE_DECLARED`, `DECLARED`, `CONFIRMED`, `CANCELLED` | | unit | Birim kopyası | | declaredAmount / UnitPrice / TotalPrice | Beyan | | confirmedAmount / UnitPrice | Onay | | remainingAmount | Lotta kalan | | isPaid, dueDate | Ödeme | | seller, imageUrls, comment | Tedarikçi ve not | | confirmedAt | Onay zamanı | ### FIFO çıkış (`stockExits`) `type`: `SALE`, `FIRE`, `ADJUSTMENT`. `reason`: hasar, SKT, kayıp, operasyon, diğer, sayım eksiği. `stockEntryReferences` hangi lottan ne kadar düşüldüğü. Sipariş satışı `buyerOrder` bağlar. ### Kurye teslimatı (`buyerOrderTransfers`) | Alan | Anlamı | | ------------------------------------------ | ------------------------ | | code, number | Kod | | status | TransferStatus | | buyer, origin, destination | Kim, nereden, nereye | | pickerOfficer, deliveryOfficer | Toplayan / teslim eden | | minDeliveryDate, maxDeliveryDate | Pencere | | buyerOrder, warehouse | Sipariş ve depo | | warehouseVehicle, warehouseVehicleTransfer | Araç ve sefer | | collectedPayment | Bu transferde tahsilat | | priority, comments, images | Operasyon | | previousDeliveryImages | Önceki teslim görselleri | Durumlar: `PENDING`, `SHIPPING`, `DELIVERED`, `CANCELLED`, `RETURNED`. ### Araç seferi (`warehouseVehicleTransfers`) `name`, `status`, `invoiceStatus` (`PENDING` / `PROCESSING` / `COMPLETED` / `PARTIAL`), şoför, araç, GPS dizisi, mesafe, süre, başlangıç-bitiş, `collectedPayments[]` (yöntem, tutar, `isPaid`). ### GPS (`warehouseVehicleLocations`) `latitude`, `longitude`, `recordedAt`. ### Tedarik talebi (`procurementRequests`) Satıcı kopyası, isteğe bağlı yetkili, `content`, `images[]`, ilçe kopyası, `status` (`PENDING`, `APPROVED`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`).