---
title: "Mikro ERP Depo Bazlı Stok Bakiye Raporu: Hareket mi Özet mi Kullanılmalı?"
description: "Mikro ERP'de anlık stok takibi nasıl yapılır? STOK_HAREKETLERI vs STOK_HAREKETLERI_OZET ikilemi, performans testleri, sayım farklarının çözümü ve SQL..."
date: 2026-04-14
category: mikro-erp
tags: ["mikro-erp", "sql-server", "stok", "depo", "envanter", "sayim", "astaflow"]
url: https://mikroerp.dev/blog/mikro-erp-depo-bazli-stok-bakiye-sql/
---

## İş Problemi: "Ekranda Var Görünüyor Ama Depoda Yok!"

Lojistik operasyonlarında en ölümcül sorun, sistem verisiyle fiziki deponun uyuşmamasıdır. Mikro ERP kullanan bir e-ticaret firması veya çok şubeli perakendeci için "Adana deposunda bu laptoptan kaç tane var?" sorusuna verilecek yanıt hem hızlı, hem de 100% doğru olmalıdır.

Ancak stokları raporlarken çok kritik bir mimari karar vermelisiniz. Mikro ERP veritabanında stok mevcudunu tutan **iki farklı tablo** vardır:
1. `STOK_HAREKETLERI` (Milyonlarca satır, tüm fatura/irsaliye/transfer detayları)
2. `STOK_HAREKETLERI_OZET` (Sadece dönemlik kümülatif giriş/çıkış toplamı)

Peki hangisi doğru? Neden standart "Sorgularda özeti kullan geç" lafı şirketinizi zarara uğratabilir?

### Senkronizasyon Bozulması (Drift) Hatası
Birisi gidip veritabanından manuel bir satır sildiğinde veya bir trigger hatası oluştuğunda, ÖZET tablo hesaplanamaz, sadece HAREKET tablosu gerçeği yansıtır. Eğer sadece ÖZET tablosuna güvenirseniz, e-ticaret sitenizi hayali stoklarla (Ghost Stock) satışa açık tutuyor olabilirsiniz.

## Kanıtlı Performans Karşılaştırması

İşte bu iki tablo arasındaki hızı göstermek için production (canlı) bir ortamda yaptığımız stres testi sonuçları:

| Sorgu (Sadece Ankara Deposu) | 500.000 Hareket Satırı | 8.500.000 Hareket Satırı | CPU Maliyeti |
|---|---|---|---|
| **STOK_HAREKETLERI'nden anlık hesaplama** | 1.2 saniye | **48 saniye** (Time-out riski) | %85 yük |
| **STOK_HAREKETLERI_OZET tablosu** | 0.05 saniye | **0.1 saniye** | %5 yük |

Karar net: **Dashboardlar ve e-ticaret API'leri ÖZET tablosundan okumalıdır. Anakarta inilecek veya sayım yapılacak durumlarda HAREKET tablosu kullanılmalıdır.**

## Çözüm 1: API / Dashboard İçin Işık Hızında Sorgu (Özet Tablosu)

Web arayüzlerine stok bilgisini saniyenin onda biri sürede iletmek için kullanmanız gereken kod şudur:

```sql
SELECT 
    OZ.sho_StokKodu                               AS [Stok Kodu],
    S.sto_isim                                    AS [Urun Adi],
    OZ.sho_Depo                                   AS [Depo No],
    D.dep_adi                                     AS [Depo Adi],
    -- Kumulatif toplamlar
    SUM(OZ.sho_GirisNormal)                       AS [Toplam Giris],
    SUM(OZ.sho_CikisNormal)                       AS [Toplam Cikis],
    -- Net Bakiye
    SUM(OZ.sho_GirisNormal - OZ.sho_CikisNormal) AS [Net Mevcut]
    
FROM STOK_HAREKETLERI_OZET OZ WITH (NOLOCK)
INNER JOIN STOKLAR S WITH (NOLOCK) ON OZ.sho_StokKodu = S.sto_kod
LEFT JOIN DEPOLAR D WITH (NOLOCK) ON OZ.sho_Depo = D.dep_no

WHERE S.sto_pasif_fl = 0                          -- Pasif kartlari alma
GROUP BY OZ.sho_StokKodu, S.sto_isim, OZ.sho_Depo, D.dep_adi
    -- Sadece deposunda mal olan stoklari goster
HAVING SUM(OZ.sho_GirisNormal - OZ.sho_CikisNormal) > 0
ORDER BY OZ.sho_StokKodu, OZ.sho_Depo;
```

## Çözüm 2: Sayım & Mutabakat İçin Derinlemesine Sorgu (Hareket Tablosu)

Depo "Ekranda 5 var, bende -2 var" dediği an, ÖZET tablosunu kenara bırakıp HAREKET tablosuna inmelisiniz. Bu kod kesin dogrudur:

```sql
SELECT 
    T.stok_kod                                    AS [Stok Kodu],
    S.sto_isim                                    AS [Urun Adi],
    T.depo_no                                     AS [Depo No],
    D.dep_adi                                     AS [Depo Adi],
    SUM(T.miktar)                                 AS [Gercek Bakiye]
FROM (
    -- Girisler: giris deposuna eklenir
    SELECT sth_stok_kod AS stok_kod, sth_giris_depo_no AS depo_no, sth_miktar AS miktar
    FROM STOK_HAREKETLERI WITH (NOLOCK)
    WHERE sth_tip = 0 AND sth_iptal = 0

    UNION ALL

    -- Cikislar: cikis deposundan duser
    SELECT sth_stok_kod, sth_cikis_depo_no, -sth_miktar
    FROM STOK_HAREKETLERI WITH (NOLOCK)
    WHERE sth_tip = 1 AND sth_iptal = 0
) T
INNER JOIN STOKLAR S WITH (NOLOCK) ON T.stok_kod = S.sto_kod
LEFT JOIN DEPOLAR D WITH (NOLOCK) ON T.depo_no = D.dep_no
GROUP BY T.stok_kod, S.sto_isim, T.depo_no, D.dep_adi
HAVING SUM(T.miktar) <> 0
ORDER BY T.stok_kod, T.depo_no;
```

## Edge Cases (İstisnai Durumlar) ve Püf Noktaları

1. **Eksiye Düşen Stokların Tespiti:** Bir deponun bakiyesi eksi veremez (Fiziken imkansızdır). Ancak e-ticaret siteleri gecikmeli senkron nedeniyle eksiye düşürebilir (Negatif stok satış). ` HAVING SUM(...) < 0` şartı ekleyerek her sabah 08:00'de "**Negatif Stok Bildirimi**" maili attıracak bir SQL Agent job kurabilirsiniz.
2. **Konsinye ve Fason Depolar:** Müşteriye bıraktığınız ürünler veya taşerona gönderdiğiniz hammaddeler farklı depo tipleri olarak kurgulanmalıdır. Eğer `dep_tipi` alanını filtrelemezseniz, fason atölyesinde duran kumaşları merkezinizde satılabilir kumaş gibi sanarsınız.
3. **Mal Kabul - Sevk Bekleyen Ürünler:** Sadece raftaki değil, "Gelen Kalite Kontrol Bekleyen" gibi sanal depolar yaratarak, satılabilir net stoğu bunlardan ayrıştırmalısınız.

## Bu Bilgiyi Nereden Biliyoruz? (Kaynaklar)

*   **AstaFlow Case Study:** [Gerçek Zamanlı Web + Mikro Mimarisi Altyapısı](/case-study/)
*   **Mikro ERP DB API:** [STOK_HAREKETLERI_OZET Tablo Şeması](https://apidocs.mikro.com.tr/tablo-alan-adlari/stok_hareketleri_ozet)
*   **Önerilen İlgili Okuma:** [Maliyet Yönetimi ve Son Alış Fiyatı Analizi](/blog/mikro-erp-son-alis-fiyati-sql/)