İçeriğe geç
ERP Asistanı
SAP SQL

SAP B1 Satış Raporu SQL: OINV ve ORIN ile Net Ciro ve KDV

SAP Business One'da OINV ve ORIN ile net ciro, KDV ve iade analizi SQL sorguları: aylık-çeyreklik kırılım, KDV oranı VatPrcnt, dövizli belge notu.

Erp Asistanı Erp Asistanı Editör ekibi 10 dk okuma
SAP B1 Satış Raporu SQL: OINV ve ORIN ile Net Ciro ve KDV

SAP Business One'da satış raporu almak isteyenlerin ilk sorusu hep aynıdır: ciro hangi tablodan okunur? Cevap iki parçalıdır: satış faturası OINV, iade faturası ORIN. İkisinin farkı net ciroyu verir; irsaliye (ODLN) bu hesaba hiç girmez, çünkü faturası irsaliyeden kopyalanan bir satış iki kez sayılır. Bu yazıda CANCELED = 'N' filtresini hiç düşürmeyen, KDV tutarını belge başlığından ve satırındaki VatPrcnt üzerinden okuyan yedi SQL sorgusu var: aylık net ciro, çeyreklik kırılım, cari bazında ciro ve iade oranı, KDV oranı bazında matrah, ürün bazında net satış, dövizli belge kontrolü ve iade faturasının kaynak faturayla eşleşmesi. Tabloları ilk kez görüyorsanız önce SAP Business One tablo yapısı rehberine bakın.

Net ciro formülü: hangi tablodan ne okunur

Rapordaki üç sayı birbirine karıştırıldığında sonuç SAP ekranındaki rakamla tutmaz. Aşağıdaki tablo hangi ihtiyacın hangi kolondan karşılandığını özetler.

İhtiyaç Tablo Kolon Not
Satış faturası tutarı OINV DocTotal, VatSum DocTotal KDV dahildir
İade faturası tutarı ORIN DocTotal, VatSum satıştan düşülür
KDV hariç ciro OINV / ORIN DocTotal - VatSum yerel para birimi
Satır bazlı matrah INV1 / RIN1 LineTotal KDV hariç, satır iskontosu düşülmüş
KDV oranı INV1 / RIN1 VatPrcnt belge anındaki oran; OVTG'den sabit oran yazmayın
Döviz tutarı OINV DocTotalFC, DocCur, DocRate yalnız dövizli belgede anlamlı
İrsaliye ODLN - ciroya EKLENMEZ

Net ciro = OINV toplamı eksi ORIN toplamı. Tutarlar yerel para birimindedir; belge dövizliyse DocTotal yine yerel karşılığı taşır, döviz tutarı DocTotalFC kolonundadır.

1. Aylık net ciro ve KDV

İki tabloyu UNION ALL ile alt alta koyup iade dalını negatif yazmak en okunur kalıptır. Böylece aynı GROUP BY hem satışı hem iadeyi tek geçişte toplar.

SELECT x.Yil, x.Ay,
       SUM(x.KdvHaric) AS NetCiro,
       SUM(x.Kdv)      AS Kdv,
       SUM(x.KdvDahil) AS BrutCiro
FROM (
    SELECT YEAR(DocDate) AS Yil, MONTH(DocDate) AS Ay,
           DocTotal - VatSum AS KdvHaric, VatSum AS Kdv, DocTotal AS KdvDahil
    FROM OINV
    WHERE CANCELED = 'N'
      AND DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
    UNION ALL
    SELECT YEAR(DocDate), MONTH(DocDate),
           -(DocTotal - VatSum), -VatSum, -DocTotal
    FROM ORIN
    WHERE CANCELED = 'N'
      AND DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
) x
GROUP BY x.Yil, x.Ay
ORDER BY x.Yil, x.Ay;

Rapor tarihi DocDate kolonudur. Vergi tarihine göre rapor isteniyorsa aynı sorguda TaxDate kullanılır; iki tarih farklı aylara düşebilir, bu yüzden SAP ekranıyla fark çıkarsa ilk bakılacak yer burasıdır.

2. Çeyreklik kırılım

Aynı kalıbın çeyrek versiyonu DATEPART(QUARTER, ...) ile kurulur ve yönetim sunumlarında aylık dalgalanmayı yumuşatır.

SELECT YEAR(x.DocDate) AS Yil,
       DATEPART(QUARTER, x.DocDate) AS Ceyrek,
       SUM(x.KdvHaric) AS NetCiro,
       SUM(x.Kdv) AS Kdv
FROM (
    SELECT DocDate, DocTotal - VatSum AS KdvHaric, VatSum AS Kdv
    FROM OINV
    WHERE CANCELED = 'N'
    UNION ALL
    SELECT DocDate, -(DocTotal - VatSum), -VatSum
    FROM ORIN
    WHERE CANCELED = 'N'
) x
GROUP BY YEAR(x.DocDate), DATEPART(QUARTER, x.DocDate)
ORDER BY Yil, Ceyrek;

3. Cari bazında net ciro ve iade oranı

Satış ve iadeyi ayrı kolonlarda göstermek, iadeyi sürekli yapan müşteriyi ciro sıralamasında yanlış okumayı engeller.

SELECT s.CardCode AS CariKod,
       c.CardName AS CariAd,
       SUM(s.Satis) AS SatisKdvHaric,
       SUM(s.Iade)  AS IadeKdvHaric,
       SUM(s.Satis + s.Iade) AS NetCiro,
       SUM(s.Kdv)   AS Kdv
FROM (
    SELECT CardCode, DocTotal - VatSum AS Satis, 0 AS Iade, VatSum AS Kdv
    FROM OINV
    WHERE CANCELED = 'N'
      AND DocDate >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1)
    UNION ALL
    SELECT CardCode, 0, DocTotal - VatSum, -VatSum
    FROM ORIN
    WHERE CANCELED = 'N'
      AND DocDate >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1)
) s
JOIN OCRD c ON c.CardCode = s.CardCode
GROUP BY s.CardCode, c.CardName
ORDER BY NetCiro DESC;

Cari adını belgedeki CardName kopyasından değil OCRD kartından okuyoruz; unvan sonradan değiştiyse belgedeki kopya eski kalır ve aynı müşteri iki satıra bölünür.

4. KDV oranı bazında matrah ve KDV

KDV kırılımını belge başlığından üretmek mümkün değildir; başlıkta yalnız toplam VatSum vardır. Oran kırılımı için satıra (INV1, RIN1) inmek ve oranı VatPrcnt kolonundan okumak gerekir.

Okuma yeri Kolon Ne verir
Belge başlığı OINV.DocTotal, OINV.VatSum belge geneli; başlık iskontosu düşülmüş
Belge satırı INV1.LineTotal, INV1.VatPrcnt satır bazlı matrah ve oran; başlık iskontosu satıra yansımaz
SELECT l.VatGroup AS KdvKodu,
       l.VatPrcnt AS KdvOrani,
       SUM(l.LineTotal) AS Matrah,
       SUM(l.VatSum)    AS KdvTutar
FROM (
    SELECT i.VatGroup, i.VatPrcnt, i.LineTotal, i.VatSum
    FROM INV1 i
    JOIN OINV f ON f.DocEntry = i.DocEntry
    WHERE f.CANCELED = 'N'
    UNION ALL
    SELECT r.VatGroup, r.VatPrcnt, -r.LineTotal, -r.VatSum
    FROM RIN1 r
    JOIN ORIN n ON n.DocEntry = r.DocEntry
    WHERE n.CANCELED = 'N'
) l
GROUP BY l.VatGroup, l.VatPrcnt
ORDER BY l.VatPrcnt;

Burada OVTG tablosundan sabit bir oran yazmak en sık yapılan hatadır: oran belge kesildiği andaki değeriyle satırda saklanır, OVTG'de sonradan değişmiş olabilir. Tarihsel rapor için doğru kaynak satırdaki VatPrcnt kolonudur.

5. Ürün bazında net satış (son 12 ay)

SELECT s.ItemCode AS StokKod,
       i.ItemName AS StokAd,
       SUM(s.Miktar) AS NetMiktar,
       SUM(s.Net)    AS NetCiro,
       SUM(s.Kdv)    AS Kdv
FROM (
    SELECT l.ItemCode, l.Quantity AS Miktar, l.LineTotal AS Net, l.VatSum AS Kdv
    FROM INV1 l
    JOIN OINV f ON f.DocEntry = l.DocEntry
    WHERE f.CANCELED = 'N'
      AND f.DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
    UNION ALL
    SELECT r.ItemCode, -r.Quantity, -r.LineTotal, -r.VatSum
    FROM RIN1 r
    JOIN ORIN n ON n.DocEntry = r.DocEntry
    WHERE n.CANCELED = 'N'
      AND n.DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
) s
JOIN OITM i ON i.ItemCode = s.ItemCode
GROUP BY s.ItemCode, i.ItemName
ORDER BY NetCiro DESC;

Ürün adını satırdaki Dscription yerine karttan (OITM.ItemName) alıyoruz: satır açıklaması belgede elle değiştirilmişse aynı ürün raporda iki satıra bölünür.

6. Dövizli belgelerde ciro karşılaştırması

DocTotal her zaman yerel para karşılığıdır. Dövizle kesilen faturaları ayırmak için para birimi kolonuna bakın.

SELECT f.DocNum AS FaturaNo,
       f.CardCode AS CariKod,
       f.DocCur AS ParaBirimi,
       f.DocRate AS Kur,
       f.DocTotal - f.VatSum AS YerelKdvHaric,
       f.DocTotalFC AS DovizKdvDahil
FROM OINV f
WHERE f.CANCELED = 'N'
  AND f.DocCur <> N'TRY'
ORDER BY f.DocDate DESC;

Yerel para kodunuz kurulumda farklı yazılmışsa (bazı şirketlerde kısaltma değişebilir) N'TRY' değerini güncelleyin. DocTotalFC döviz toplamı, DocRate belge kuru, DocCur belge para birimidir.

7. İade faturası hangi faturayı düzeltiyor?

İade satırları kaynak faturaya BaseType = 13 ve BaseEntry ile bağlanır. Bu bağ, hangi faturanın ne kadar geri döndüğünü gösterir.

SELECT r.DocNum AS IadeNo,
       r.DocDate AS Tarih,
       r.CardCode AS CariKod,
       c.CardName AS CariAd,
       r.DocTotal - r.VatSum AS IadeKdvHaric,
       r.VatSum AS IadeKdv,
       MAX(f.DocNum) AS KaynakFaturaNo
FROM ORIN r
JOIN OCRD c ON c.CardCode = r.CardCode
LEFT JOIN RIN1 rl ON rl.DocEntry = r.DocEntry AND rl.BaseType = 13
LEFT JOIN OINV f ON f.DocEntry = rl.BaseEntry
WHERE r.CANCELED = 'N'
GROUP BY r.DocNum, r.DocDate, r.CardCode, c.CardName, r.DocTotal, r.VatSum
ORDER BY r.DocDate DESC;

İade irsaliyesi (ORDN) ayrı bir belgedir ve ciro hesabına girmez; cirodan düşen belge ORIN iade faturasıdır. Demo şirketlerde iade tabloları boş olabilir, bu sorgunun iade dalının gereksiz olduğu anlamına gelmez.

Sık yapılan hatalar

  • İrsaliyeyi ciroya eklemek: ODLN satışa eklenirse faturası kesilmiş sevkiyatlar iki kez sayılır. Kaynak daima OINV eksi ORIN.
  • DocTotal'ı KDV hariç sanmak: DocTotal KDV dahildir; KDV hariç tutar DocTotal - VatSum ile bulunur.
  • KDV oranını OVTG'den yazmak: oran satırda VatPrcnt olarak saklanır, OVTG güncel değer taşır ve tarihsel raporu bozar.
  • Başlık iskontosunu satırda aramak: OINV.DiscPrcnt satırlara yansımaz; bu yüzden SUM(LineTotal) ile DocTotal - VatSum bazen eşit çıkmaz. Belge toplamı için başlık, kalem kırılımı için satır okunur.
  • CANCELED filtresini unutmak: iptal edilen belge ile onu ters çeviren iptal belgesi birlikte toplanınca tutar ikiye katlanır.
  • JOIN'i DocNum ile kurmak: belge numarası seriye göre tekrar edebilir; bağlama daima DocEntry ile yapılır.
  • Türkçe metni N öneksiz aramak: LIKE N'%...%' kullanın, aksi halde ş, ğ, İ harfleri sessizce bozulur.

Sık sorulanlar

Net ciro ile brüt ciro arasındaki fark nedir? Brüt ciro OINV toplamıdır, iade düşülmemiştir. Net ciro aynı toplamdan ORIN tutarının çıkarılmasıyla bulunur. İkisini aynı raporda ayrı kolonlarda göstermek, iade oranı yüksek müşteriyi erken fark etmeyi sağlar.

Ciro raporum SAP ekranındaki rakamla tutmuyor, nereden başlamalıyım? Sırayla şu üçünü kontrol edin: iadeler (ORIN) düşülüyor mu, DocTotal ile DocTotal - VatSum karıştırılmış mı, CANCELED = 'N' filtresi var mı. Dördüncü olasılık tarih seçimidir; SAP bazı raporlarda DocDate yerine TaxDate kullanır.

Satırdaki VatPrcnt boş ya da sıfır görünüyor, neden? Hizmet belgelerinde (DocType = 'S') satırda mal kodu yerine hesap kodu bulunur ve KDV bilgisi tanıma göre değişebilir. Ayrıca KDV istisnası uygulanan satırlarda oran sıfır olabilir; bu satırları VatGroup kolonuyla ayrı okuyup rapora not düşmek gerekir.

Bu sorgular HANA sürümünde de çalışır mı? Hayır. Buradaki sorgular SQL Server (T-SQL) sözdizimiyle yazıldı; DATEADD, DATEFROMPARTS ve DATEPART çağrıları HANA'da karşılıksızdır ve tablo adları çift tırnakla yazılır. HANA tarafında sorguların uyarlanması gerekir.


Bu yedi sorgu satış raporunuzun çekirdeğini kurar: OINV eksi ORIN ile net ciro, satırdaki VatPrcnt ile KDV kırılımı, DocCur ile döviz kontrolü. Bakiyeyi ve vade tarafını da eklemek isterseniz SAP Business One cari bakiye ve yaşlandırma SQL yazısı JDT1 tarafını anlatıyor; daha fazla kopyala-çalıştır örnek için SAP Business One hazır SQL sorguları listesine bakabilirsiniz.

Sorguyu her rapor için elle uyarlamak yerine sorunuzu Türkçe yazabilirsiniz: Erp Asistanı SAP Business One şemanıza uygun, doğrulanmış SQL'i saniyeler içinde üretir.

Ücretsiz üye olun, SAP satış sorgunuzu doğal dille üretin →

Bu yazıyı paylaş
Konuşarak raporlayın

SAP Business One'da SQL ve raporu konuşarak alın

Türkçe sorunuzu yazın, şemanıza uygun çalışan SQL'i ya da hazır uygulamanızı saniyeler içinde alın.