---
title: "Mikro ERP 046355 Cari Risk Raporunu SQL ile Yeniden Üretmek: fn_CariRiskFoyu Analizi"
description: "Mikro ERP 046355 Detaylı Cari Bakiye-Ciro-Risk-Teminat raporunu SQL ile nasıl çözdük? fn_CariRiskFoyu fonksiyonu, ciro hesabının gerçek kaynağı, KDV tuzağı, çek/senet risk süresi ve performans optimizasyonu."
date: 2026-05-25
category: mikro-erp
tags: ["mikro-erp", "sql-server", "cari-hesap", "risk-raporu", "fn_CariRiskFoyu", "046355", "cari-risk-foyu", "cek-senet", "performans", "astaflow"]
url: https://mikroerp.dev/blog/mikro-erp-cari-risk-raporu-fn-caririsklfoyu-analizi/
---

## İş Problemi: Mikro'nun Hazır Raporu Var — Neden SQL ile Uğraşıyoruz?

Mikro ERP içinde şu rapor zaten mevcut:

> **(K) Detaylı Cari Hesap Bakiye-Ciro-Risk-Teminat Karşılaştırma Raporu (046355)**

Mikro menüsünde **046355** numarasıyla bulunan bu rapor (benzer işlevi gören 046356 numaralı rapordan daha detaylı parametrelere sahiptir), tek ekranda cari kodu, toplam ciro, kredi toplamı, açık sipariş, faturalaşmamış irsaliye, açık hesap, kredi limiti, çek/senet detayı, ödenmeyen toplam ve toplam riski gösteriyor. Hızlı özet için **041000 Cari Hesap Risk Föyü** de kullanılabilir ama 046355 çok daha kapsamlıdır.

Ama sorunlar var:

1. **Çok yavaş.** 1600+ cari için Mikro'nun orijinal raporu **45 dakikanın üzerinde** sürüyor.
2. **Kapalı kutu.** Hangi tablolardan ne çektiğini göremiyorsunuz.
3. **Dışarı taşıyamıyorsunuz.** Sonuçları web dashboard'a, Excel otomasyonuna veya özel uyarı sistemine aktarmak istediğinizde Mikro'nun arayüzüne bağımlı kalıyorsunuz.

Bu yazıda o raporu SQL tarafında birebir yeniden üretme sürecimizi anlatıyoruz. Üstelik optimize ettiğimiz SQL versiyonu **aynı sonucu ~15 dakikada** üretiyor — Mikro'nun orijinalinden 3 kat daha hızlı. Yanlış varsayımları, çıkmaz sokakları ve sonunda çalışan çözümü paylaşıyoruz.

## Hedef: Raporun Ürettiği Kolonları SQL ile Eşleştirmek

Rapor çıktısındaki kolonlar:

| Kolon | Açıklama |
|---|---|
| Cari hesap kodu | Cari kart kodu |
| Cari hesap adı | Unvan |
| Temsilci kodu | Cari temsilcisi |
| Toplam ciro | Belirli tarih aralığında net satış cirosu |
| Kredi toplamı | Cariye tanımlı kredi limiti |
| Açık sipariş | Henüz teslim edilmemiş sipariş tutarı |
| Faturalaşmamış irsaliye | Sevk edilmiş ama faturası kesilmemiş mal |
| Açık hesap | Mevcut borç/alacak bakiyesi |
| Kredi limiti | Kullanılan kredi − toplam kredi |
| Kendi çeki / Müşterisinin çeki | Çek pozisyonları |
| Kendi senedi / Müşterisinin senedi | Senet pozisyonları |
| Ödenmeyen toplam | Tüm çek + senet toplamı |
| Toplam risk | Açık hesap + açık sipariş + irsaliye + çek/senet |

Doğrulama için tek bir cari seçtik ve Mikro raporundaki değerlerle SQL sonucumuzu satır satır karşılaştırdık.

## İlk Adım: Mikro Ne Çalıştırıyor?

Rapor Mikro arayüzünde çalışırken SQL Server üzerindeki aktif session'ları izledik:

```sql
SELECT 
    r.session_id,
    s.login_name,
    s.host_name,
    r.status,
    r.total_elapsed_time / 1000 AS elapsed_seconds,
    r.cpu_time,
    LEFT(t.text, 4000) AS running_sql
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s
    ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE s.program_name LIKE '%ABORON%'  -- Mikro ERP istemci adı
  AND r.session_id <> @@SPID
ORDER BY r.total_elapsed_time DESC;
```

Bu şekilde Mikro'nun arka planda hangi fonksiyonu çağırdığını yakaladık: **`dbo.fn_CariRiskFoyu`**.

## fn_CariRiskFoyu: Risk Tarafının Kalbi

Fonksiyonun tanımını `sp_helptext` ile çektik. İçeride ciddi bir yapı var:

**Hesapladığı bileşenler:**
- Açık hesap bakiyesi
- Açık sipariş tutarı
- Faturalaşmamış irsaliye
- Kendi çeki / Müşterisinin çeki
- Kendi senedi / Müşterisinin senedi
- Kredi limiti / Kullanılan kredi
- Cari teminatlar

**Kullandığı tablolar:**

```
CARI_HESAPLAR, CARI_HESAP_TEMINATLARI, SIPARISLER,
STOK_HAREKETLERI, KONSINYE_HAREKETLERI, ODEME_EMIRLERI, FIRMALAR
```

**İçeride çağırdığı diğer fonksiyonlar:**

```
fn_CariHesapOrjinalDovizBakiye, fn_CariHesapAnaDovizBakiye,
fn_KurBul, fn_Evrak_Kalan_Miktar, fn_StokSatisFiyati,
fn_DinamikRiskOranlari
```

Fonksiyon bir **table-valued function** — her cari için detay satırları döndürüyor. Her satırda bir `TipNo` var:

| TipNo | Anlam |
|---|---|
| 1 | Açık hesap |
| 2 | Kendi çeki |
| 3 | Müşterisinin çeki |
| 4 | Kendi senedi |
| 5 | Müşterisinin senedi |
| 8 | Faturalaşmamış irsaliye |
| 9 | Açık sipariş |

## Beş Kritik Keşif

Bu raporu birebir eşleştirene kadar beş önemli tuzağa düştük. Her biri ayrı bir ders.

### 1. Toplam Ciro: `CARI_HESAP_HAREKETLERI` Değil, `STOK_HAREKETLERI`

İlk denemede toplam ciroyu `CARI_HESAP_HAREKETLERI` tablosundan hesapladık. Mikro raporuyla eşleşmedi:

| Kaynak | Sonuç |
|---|---|
| `CARI_HESAP_HAREKETLERI` / `cha_meblag` | 1.641.394,76 |
| `CARI_HESAP_HAREKETLERI` net tahmini | 1.375.782,65 |
| **Mikro rapor** | **1.362.408,25** |
| `STOK_HAREKETLERI` net satış satır toplamı | **1.362.408,25** ✓ |

**Ders:** Cari hareket tablosu "ciro" değil — tahsilat, vade farkı, kur farkı gibi finansal hareketleri de içerir. Mikro'nun ciro mantığı stok/fatura satırlarından geliyor.

Doğru formül:

```sql
SUM(
    CASE WHEN ISNULL(sth_normal_iade, 0) = 1 THEN -1 ELSE 1 END
    * (
        sth_tutar
        - (sth_iskonto1 + sth_iskonto2 + sth_iskonto3 
         + sth_iskonto4 + sth_iskonto5 + sth_iskonto6)
        + (sth_masraf1 + sth_masraf2 + sth_masraf3 + sth_masraf4)
    )
)
```

Filtreler: `sth_iptal = 0`, `sth_fat_uid` dolu (faturalaşmış satırlar), tarih aralığı.

### 2. Açık Sipariş: KDV Dahil/Hariç Farkı

İlk sipariş hesabımız `28.168,68` verdi. Mikro raporu `23.473,90` gösteriyordu.

```
23.473,90 × 1,20 = 28.168,68
```

Tam %20 KDV farkı. Rapor parametresinde "İrsaliye ve sipariş KDV dahil raporlansın" seçili **değildi**. KDV hariç hesaplamak gerekiyordu.

Birim fiyat formülü:

```sql
(
    sip_tutar
    - (sip_iskonto_1 + ... + sip_iskonto_6)
    + (sip_masraf_1 + ... + sip_masraf_4)
    + CASE WHEN @SiparisIrsaliyeKDVDahil = 1 
        THEN (sip_vergi + sip_masvergi + sip_Otv_Vergi + sip_otvtutari) 
        ELSE 0 
      END
) / NULLIF(sip_miktar, 0)
```

Kalan miktar: `fn_Evrak_Kalan_Miktar(sip_miktar, sip_teslim_miktar, sip_kapat_fl)`

### 3. Çek/Senet: `TipAdi LIKE` Değil, `TipNo` Kullanın

İlk denemede fonksiyon çıktısındaki metin alanıyla eşleşme yapmaya çalıştık:

```sql
-- YANLIŞ: Metin bazlı eşleşme güvenilir değil
WHERE TipAdi LIKE '%çek%'
```

Doğru yöntem, `TipNo` integer alanını kullanmak:

```sql
-- DOĞRU: TipNo ile kesin eşleşme
SUM(CASE WHEN TipNo = 3 THEN ISNULL(AnaDovizTutar, 0) ELSE 0 END)
    AS MusterisininCeki
```

### 4. Cirolanan Çek/Senet Risk Süresi: NULL Verilirse Sonuç Eksik Gelir

İlk `fn_CariRiskFoyu` çağrısında `@cirocekilkvade` ve `@cirosenetilkvade` parametrelerini `NULL` vermiştik. Müşteri çeki ve senedi **eksik** geliyordu.

Rapor parametrelerinde tanımlı:
- Cirolanan çek vade sonrası risk süresi: **10 gün**
- Cirolanan senet vade sonrası risk süresi: **30 gün**

SQL karşılığı:

```sql
DECLARE @CiroCekIlkVade DATETIME 
    = DATEADD(DAY, -@CiroCekRiskSuresiGun, @Tarih);
DECLARE @CiroSenetIlkVade DATETIME 
    = DATEADD(DAY, -@CiroSenetRiskSuresiGun, @Tarih);
```

Bu düzeltmeden sonra çek/senet değerleri raporla birebir eşleşti.

### 5. `fn_CariRiskFoyu` Her Cari İçin Ayrı Çalışıyor

Fonksiyon `CROSS APPLY` ile her cari satırı için tekrar tekrar yürütülüyor. İçeride çok sayıda tablo ve scalar fonksiyon çağrısı var.

```
Mikro orijinal rapor (046355):  1600+ cari → 45+ dakika
Optimize SQL sorgumuz:          1600+ cari → ~15 dakika (3x hızlı)
```

Tek cari için kabul edilebilir, ama toplu rapor için ciddi darboğaz. Yine de Mikro'nun orijinal raporuna kıyasla temp tablo + index optimizasyonu ile ciddi hız kazanımı sağladık.

## Doğrulama: Tek Cari Eşleşme Testi

Sorgu sonucunu Mikro 046355 raporuyla tek cari üzerinden birebir doğruladık:

```
Cari: [Örnek Cari] — Reklam ve Kırtasiye sektörü

Toplam ciro:              1.362.408,25  ✓
Kredi toplamı:            3.500.000,00  ✓
Açık sipariş:                23.473,90  ✓
Faturalaşmamış irsaliye:          0,00  ✓
Açık hesap:               2.896.672,94  ✓
Kredi limiti:              -575.158,38  ✓
Kendi çeki:                       0,00  ✓
Müşterisinin çeki:          691.362,19  ✓
Kendi senedi:                     0,00  ✓
Müşterisinin senedi:        102.000,00  ✓
Ödenmeyen toplam:           793.362,19  ✓
Toplam risk:              3.713.509,03  ✓
```

Tüm değerler kuruşuna kadar eşleşti.

## Nihai Optimize SQL Sorgusu

Aşağıdaki sorgu temp tablolar ve clustered index'ler ile optimize edilmiş nihai versiyondur:

```sql
SET NOCOUNT ON;

-- =============================================
-- ⚙️ AYARLAR: Kendi ortamınıza göre değiştirin
-- =============================================
DECLARE @FirmaNo INT = 0;
DECLARE @Tarih DATETIME = GETDATE();
DECLARE @CiroBaslangicTarihi DATETIME = '20260101';  -- ⚙️ Ciro başlangıcı
DECLARE @CariKodLike NVARCHAR(25) = 'M.35%';         -- ⚙️ Cari filtresi
DECLARE @SrmMerkezKodu NVARCHAR(25) = '';
DECLARE @BagliCarileriBirlikteHesapla BIT = 0;
DECLARE @TeminattaVadeKontrol BIT = 0;
DECLARE @SiparisIrsaliyeKDVDahil BIT = 0;            -- ⚙️ KDV dahil/hariç
DECLARE @CiroCekRiskSuresiGun INT = 10;               -- ⚙️ Çek risk süresi
DECLARE @CiroSenetRiskSuresiGun INT = 30;              -- ⚙️ Senet risk süresi

DECLARE @CiroCekIlkVade DATETIME 
    = DATEADD(DAY, -@CiroCekRiskSuresiGun, @Tarih);
DECLARE @CiroSenetIlkVade DATETIME 
    = DATEADD(DAY, -@CiroSenetRiskSuresiGun, @Tarih);

IF OBJECT_ID('tempdb..#CariBase') IS NOT NULL DROP TABLE #CariBase;
IF OBJECT_ID('tempdb..#Ciro') IS NOT NULL DROP TABLE #Ciro;
IF OBJECT_ID('tempdb..#AcikSiparis') IS NOT NULL DROP TABLE #AcikSiparis;
IF OBJECT_ID('tempdb..#RiskOzet') IS NOT NULL DROP TABLE #RiskOzet;

------------------------------------------------------------
-- 1) Cari listesi
------------------------------------------------------------
SELECT
    ch.cari_kod,
    ch.cari_unvan1,
    ch.cari_unvan2,
    ch.cari_temsilci_kodu
INTO #CariBase
FROM CARI_HESAPLAR ch WITH (NOLOCK)
WHERE ch.cari_kod LIKE @CariKodLike;

CREATE UNIQUE CLUSTERED INDEX IX_CariBase ON #CariBase(cari_kod);

------------------------------------------------------------
-- 2) Toplam ciro — STOK_HAREKETLERI net satış satır toplamı
------------------------------------------------------------
SELECT
    sth.sth_cari_kodu AS cari_kod,
    SUM(
        CASE WHEN ISNULL(sth.sth_normal_iade, 0) = 1 
             THEN -1 ELSE 1 END
        * (
            ISNULL(sth.sth_tutar, 0)
            - (ISNULL(sth.sth_iskonto1, 0) + ISNULL(sth.sth_iskonto2, 0)
             + ISNULL(sth.sth_iskonto3, 0) + ISNULL(sth.sth_iskonto4, 0)
             + ISNULL(sth.sth_iskonto5, 0) + ISNULL(sth.sth_iskonto6, 0))
            + (ISNULL(sth.sth_masraf1, 0) + ISNULL(sth.sth_masraf2, 0)
             + ISNULL(sth.sth_masraf3, 0) + ISNULL(sth.sth_masraf4, 0))
        )
    ) AS ToplamCiro
INTO #Ciro
FROM STOK_HAREKETLERI sth WITH (NOLOCK)
JOIN #CariBase cb ON cb.cari_kod = sth.sth_cari_kodu
WHERE sth.sth_tarih >= @CiroBaslangicTarihi
  AND sth.sth_tarih <= @Tarih
  AND ISNULL(sth.sth_iptal, 0) = 0
  AND sth.sth_fat_uid IS NOT NULL
  AND sth.sth_fat_uid <> '00000000-0000-0000-0000-000000000000'
GROUP BY sth.sth_cari_kodu;

CREATE UNIQUE CLUSTERED INDEX IX_Ciro ON #Ciro(cari_kod);

------------------------------------------------------------
-- 3) Açık sipariş — KDV parametresiyle
------------------------------------------------------------
SELECT
    sip.sip_musteri_kod AS cari_kod,
    SUM(
        CASE WHEN sip.sip_tip = 0 THEN 1 ELSE -1 END
        * dbo.fn_Evrak_Kalan_Miktar(
            sip.sip_miktar, sip.sip_teslim_miktar, sip.sip_kapat_fl
          )
        * (
            (
                sip.sip_tutar
                - (sip.sip_iskonto_1 + sip.sip_iskonto_2 
                 + sip.sip_iskonto_3 + sip.sip_iskonto_4
                 + sip.sip_iskonto_5 + sip.sip_iskonto_6)
                + (sip.sip_masraf_1 + sip.sip_masraf_2
                 + sip.sip_masraf_3 + sip.sip_masraf_4)
                + CASE WHEN @SiparisIrsaliyeKDVDahil = 1
                    THEN (sip.sip_vergi + sip.sip_masvergi 
                        + sip.sip_Otv_Vergi + sip.sip_otvtutari)
                    ELSE 0 END
            ) / NULLIF(sip.sip_miktar, 0)
        )
        * CASE WHEN sip.sip_doviz_cinsi > 0
            THEN dbo.fn_KurBul(
                @Tarih, sip.sip_doviz_cinsi,
                dbo.fn_CariKurTipi(sip.sip_musteri_kod)
            )
            ELSE 1 END
    ) AS AcikSiparisTutar
INTO #AcikSiparis
FROM SIPARISLER sip WITH (NOLOCK)
JOIN #CariBase cb ON cb.cari_kod = sip.sip_musteri_kod
WHERE sip.sip_kapat_fl = 0
  AND sip.sip_miktar > sip.sip_teslim_miktar
  AND (sip.sip_cari_sormerk = @SrmMerkezKodu OR @SrmMerkezKodu = '')
GROUP BY sip.sip_musteri_kod;

CREATE UNIQUE CLUSTERED INDEX IX_AcikSiparis 
    ON #AcikSiparis(cari_kod);

------------------------------------------------------------
-- 4) Risk özet — fn_CariRiskFoyu (en ağır bölüm)
------------------------------------------------------------
SELECT
    cb.cari_kod,
    SUM(ISNULL(rf.[msg_S_1480\T], 0)) AS KrediToplami,
    SUM(ISNULL(rf.[msg_S_1476\T], 0)) AS KullanilanKredi,
    SUM(CASE WHEN rf.[#msg_S_1720] = 1 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) AS AcikHesap,
    SUM(CASE WHEN rf.[#msg_S_1720] = 8 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) 
        AS FaturalasmamisIrsaliye,
    SUM(CASE WHEN rf.[#msg_S_1720] = 2 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) AS KendiCeki,
    SUM(CASE WHEN rf.[#msg_S_1720] = 3 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) 
        AS MusterisininCeki,
    SUM(CASE WHEN rf.[#msg_S_1720] = 4 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) AS KendiSenedi,
    SUM(CASE WHEN rf.[#msg_S_1720] = 5 
        THEN ISNULL(rf.[msg_S_0103\T], 0) ELSE 0 END) 
        AS MusterisininSenedi
INTO #RiskOzet
FROM #CariBase cb
CROSS APPLY dbo.fn_CariRiskFoyu(
    @FirmaNo, cb.cari_kod,
    @CiroCekIlkVade, @CiroSenetIlkVade, @Tarih,
    0, @SrmMerkezKodu,
    @TeminattaVadeKontrol, @BagliCarileriBirlikteHesapla
) rf
GROUP BY cb.cari_kod;

CREATE UNIQUE CLUSTERED INDEX IX_RiskOzet ON #RiskOzet(cari_kod);

------------------------------------------------------------
-- 5) Final rapor
------------------------------------------------------------
SELECT
    cb.cari_kod                     AS [Cari hesap kodu],
    LTRIM(RTRIM(
        ISNULL(cb.cari_unvan1, '') + ' ' + ISNULL(cb.cari_unvan2, '')
    ))                              AS [Cari hesap adı],
    cb.cari_temsilci_kodu           AS [Temsilci kodu],
    ROUND(ISNULL(c.ToplamCiro, 0), 2)         AS [Toplam ciro],
    ROUND(ISNULL(ro.KrediToplami, 0), 2)      AS [Kredi toplamı],
    ROUND(ISNULL(sip.AcikSiparisTutar, 0), 2) AS [Açık sipariş],
    ROUND(ISNULL(ro.FaturalasmamisIrsaliye, 0), 2) 
                                    AS [Faturalaşmamış irsaliye],
    ROUND(ISNULL(ro.AcikHesap, 0), 2)         AS [Açık hesap],
    ROUND(
        ISNULL(ro.KullanilanKredi, 0) - ISNULL(ro.KrediToplami, 0), 2
    )                               AS [Kredi limiti],
    ROUND(ISNULL(ro.KendiCeki, 0), 2)         AS [Kendi çeki],
    ROUND(ISNULL(ro.MusterisininCeki, 0), 2)   AS [Müşterisinin çeki],
    ROUND(ISNULL(ro.KendiSenedi, 0), 2)       AS [Kendi senedi],
    ROUND(ISNULL(ro.MusterisininSenedi, 0), 2) AS [Müşterisinin senedi],
    ROUND(
        ISNULL(ro.KendiCeki, 0) + ISNULL(ro.MusterisininCeki, 0)
      + ISNULL(ro.KendiSenedi, 0) + ISNULL(ro.MusterisininSenedi, 0), 2
    )                               AS [Ödenmeyen toplam],
    ROUND(
        ISNULL(ro.AcikHesap, 0) + ISNULL(sip.AcikSiparisTutar, 0)
      + ISNULL(ro.FaturalasmamisIrsaliye, 0)
      + ISNULL(ro.KendiCeki, 0) + ISNULL(ro.MusterisininCeki, 0)
      + ISNULL(ro.KendiSenedi, 0) + ISNULL(ro.MusterisininSenedi, 0), 2
    )                               AS [Toplam risk]
FROM #CariBase cb
LEFT JOIN #RiskOzet ro    ON ro.cari_kod = cb.cari_kod
LEFT JOIN #AcikSiparis sip ON sip.cari_kod = cb.cari_kod
LEFT JOIN #Ciro c          ON c.cari_kod = cb.cari_kod
WHERE ISNULL(c.ToplamCiro, 0) <> 0
   OR ISNULL(ro.KrediToplami, 0) <> 0
   OR ISNULL(sip.AcikSiparisTutar, 0) <> 0
   OR ISNULL(ro.AcikHesap, 0) <> 0
   OR ISNULL(ro.KendiCeki, 0) <> 0
   OR ISNULL(ro.MusterisininCeki, 0) <> 0
   OR ISNULL(ro.KendiSenedi, 0) <> 0
   OR ISNULL(ro.MusterisininSenedi, 0) <> 0
ORDER BY [Toplam risk] DESC, cb.cari_kod;
```

## Performans: Darboğaz ve Optimizasyon

### Darboğaz Analizi

Ana performans sorunu `CROSS APPLY fn_CariRiskFoyu` bölümüdür. Fonksiyon her cari için bağımsız çalışır ve içeride `fn_CariHesapAnaDovizBakiye`, `fn_KurBul`, `fn_Evrak_Kalan_Miktar` gibi alt fonksiyonları çağırır.

```
Mikro 046355 orijinal rapor:    1600+ cari → 45+ dakika
Optimize SQL sorgumuz:          1600+ cari → ~15 dakika
Kazanım:                        ~3x daha hızlı
```

### Uygulanan Optimizasyonlar

Bu sorguda darboğazı hafifletmek için şunları yaptık:

1. **Temp tablo mimarisi** — Her bileşen ayrı `#TempTable`'a alındı.
2. **Clustered index** — Her temp tabloya `cari_kod` üzerinde index eklendi.
3. **Ciro ve sipariş ayrıştırma** — Bu iki kalem fonksiyon dışında hesaplandı, böylece fonksiyonun yükü azaldı.
4. **Filtre daraltma** — `@CariKodLike` ile sadece ilgili cariler işlendi.

### Orta Vadeli Çözüm: Snapshot Tablo

Rapor sık kullanılacaksa canlı çalıştırmak yerine periyodik snapshot oluşturulmalıdır:

```sql
-- Örnek snapshot tablo
CREATE TABLE dbo.CariRiskSnapshot (
    cari_kod          NVARCHAR(25) PRIMARY KEY,
    cari_ad           NVARCHAR(200),
    temsilci_kodu     NVARCHAR(25),
    toplam_ciro       DECIMAL(18,2),
    kredi_toplami     DECIMAL(18,2),
    acik_siparis      DECIMAL(18,2),
    faturalasmamis    DECIMAL(18,2),
    acik_hesap        DECIMAL(18,2),
    kredi_limiti      DECIMAL(18,2),
    kendi_ceki        DECIMAL(18,2),
    musteri_ceki      DECIMAL(18,2),
    kendi_senedi      DECIMAL(18,2),
    musteri_senedi    DECIMAL(18,2),
    odenmeyen_toplam  DECIMAL(18,2),
    toplam_risk       DECIMAL(18,2),
    snapshot_tarihi   DATETIME DEFAULT GETDATE()
);
```

Bu tablo SQL Agent job ile doldurulabilir:

- **Gece 01:00** — Tüm cariler için hesapla.
- **Gün içi** — Dashboard bu tabloyu okur. Anında yanıt, sıfır bekleme.
- **30 dakikada bir** — Daha güncel veri gerekiyorsa interval kısaltılabilir.

## Rapor Parametreleri: SQL Karşılıkları

Mikro 046355 raporunu SQL ile birebir eşleştirmek istiyorsanız, rapor ekranındaki parametreleri SQL değişkenlerine çevirmeniz gerekir. Ayrıca kredi ve risk belirleme kriterleri **Firma Tanıtım Kartı (501110)** ekranından da kontrol edilmelidir.

| Mikro Parametre | SQL Değişkeni | Varsayılan |
|---|---|---|
| Listeleme yapısı | `@CariKodLike` | `'M.35%'` |
| Ciro başlangıç tarihi | `@CiroBaslangicTarihi` | `'20260101'` |
| Cirolanan çek vade risk süresi | `@CiroCekRiskSuresiGun` | `10` |
| Cirolanan senet vade risk süresi | `@CiroSenetRiskSuresiGun` | `30` |
| İrsaliye/sipariş KDV dahil | `@SiparisIrsaliyeKDVDahil` | `0` |
| Vadesi geçmiş teminat raporlansın | `@TeminattaVadeKontrol` | `0` |
| Döviz cinsi | Fonksiyon içi | Ana döviz |

## Edge Cases (İstisnai Durumlar)

1. **Dövizli siparişler:** Açık sipariş hesabında dövizli siparişler `fn_KurBul` ile güncel kura çevrilir. Kur tanımlanmamışsa tutar 0 gelebilir.
2. **Bağlı cariler:** `@BagliCarileriBirlikteHesapla = 1` yapılırsa bağlı cari bakiyeleri de ana cariye eklenir. Bu durumda sonuçlar farklılaşır.
3. **Sorumluluk merkezi filtresi:** `@SrmMerkezKodu` boş bırakılmazsa sadece o sorumluluk merkezinin verileri gelir.
4. **İptal kayıtları:** Hem stok hareketlerinde hem siparişlerde `sth_iptal = 0` ve `sip_kapat_fl = 0` filtreleri kritiktir.

## Bu Bilgiyi Nereden Biliyoruz? (Kaynaklar)

*   **AstaFlow Case Study:** [Finans ve Tahsilat Hedeflemesi Modülleri](/case-study/)
*   **Mikro ERP DB API:** [CARI_HESAPLAR](https://apidocs.mikro.com.tr/tablo-alan-adlari/cari_hesaplar) | [SIPARISLER](https://apidocs.mikro.com.tr/tablo-alan-adlari/siparisler) | [STOK_HAREKETLERI](https://apidocs.mikro.com.tr/tablo-alan-adlari/stok_hareketleri)
*   **İlgili Yazı:** [Cari Risk Raporu: Bakiye, Açık Sipariş ve Teminat Tek Sorguda](/blog/mikro-erp-cari-risk-raporu-sql/) — CTE tabanlı basitleştirilmiş risk analizi
*   **İlgili Yazı:** [Cari Yaşlandırma SQL Sorgusu](/blog/mikro-erp-cari-yaslandirma-sql-sorgusu/) — Vade bazlı gecikme analizi
*   **İlgili Yazı:** [Açık Sipariş ve Teslimat Raporu](/blog/mikro-erp-acik-siparis-teslimat-raporu-sql/)
*   **İlgili Araç:** [Evrak Tipi Decoder — sth_tip, cha_evrak_tip değerlerini anında çevirin](/araclar/evrak-tip-decoder/)
*   **İlgili Araç:** [Fonksiyon Sözlüğü — fn_CariRiskFoyu ve diğer dbo.fn_ referansları](/araclar/fonksiyon-sozlugu/)