ERP Asistanı Dal Net
Logo SQL

Logo Banka Hareketleri SQL: BNFLINE ile Bakiye ve Ekstre

Logo'da banka bakiyesi ve ekstre BNFLINE tablosundan hesaplanır. BNACCREF bağı, SIGN yönü, yürüyen bakiye, döviz ve aylık nakit akışı sorguları.

Erp Asistanı Erp Asistanı Editör ekibi 9 dk okuma
Logo Banka Hareketleri SQL: BNFLINE ile Bakiye ve Ekstre

Logo'da banka hesabının bakiyesi hesap kartında yazmaz. BANKACC kartı yalnızca hesabın kimliğini (kod, tanım, IBAN, döviz cinsi) tutar; parayı hareket ettiren her satır BNFLINE tablosuna düşer. Yani "bankanın bakiyesi kaç" sorusunun cevabı her zaman bir toplama işlemidir: BNFLINE satırlarını SIGN yönüne göre toplamak. Bu yazıda hesap listesi bakiyesinden başlayıp tek hesap ekstresine, yürüyen bakiyeye, döviz bakiyesine ve aylık nakit akışına kadar yedi sorgu kuruyoruz. Hepsi T-SQL'dir ve gerçek bir Logo şemasındaki mantıksal tablo adlarıyla yazılmıştır.

Önce önek kuralı

BNFLINE ve BNFICHE dönem tablolarıdır; kendi veritabanınızda başına firma ve dönem öneki eklemelisiniz: LG_{firma}_{dönem}_BNFLINE (örneğin LG_323_01_BNFLINE). BANKACC ve CLCARD firma-master tablolardır: LG_{firma}_BANKACC. Aşağıdaki sorgularda okunabilirlik için önekleri kaldırdık. Tablo adlandırma mantığını daha geniş anlatan Logo tablo yapısı rehberine göz atabilirsiniz.

Hareketin üç tablosu: BNFLINE, BANKACC, BNFICHE

İlişki zinciri kısadır ve hep LOGICALREF üzerinden kurulur, kod üzerinden değil:

  • BNFLINE.BNACCREF = BANKACC.LOGICALREF - hareketin hangi banka hesabına ait olduğu. Bu tabloda BANKACCREF diye bir kolon yoktur; ilk denemede en çok bu isim uydurulur ve sorgu "Invalid column name" ile düşer.
  • BNFLINE.SOURCEFREF = BNFICHE.LOGICALREF - hareketin bağlı olduğu banka fişi (fiş no buradan gelir).
  • BANKACC.BANKREF = BNCARD.LOGICALREF - hesabın bağlı olduğu banka kurumu.
Kolon Anlamı Tuzak
BNACCREF Banka hesabı bağı BANKACCREF yazmayın, kolon adı BNACCREF
SIGN 0 = borç (para girişi), 1 = alacak (para çıkışı) SUM(AMOUNT) tek başına bakiyeyi ters verir
AMOUNT Yerel para tutarı Döviz hesapta bu TL karşılığıdır, döviz tutarı değil
TRNET / TRCURR / TRRATE Döviz tutarı / döviz kodu / kur Döviz bakiye için AMOUNT değil TRNET toplanır
DATE_ Hareket tarihi (datetime) Saat bilgisi ayrı kolondadır, tarih filtresi DATE_ ile verilir
CANCELLED 0 = aktif, 1 = iptal Her toplamada CANCELLED = 0 şart
CLIENTREF Karşı cari (havale/EFT) Boş olabilir; banka içi virmanda cari yoktur
TRCODE / MODULENR Hareket türü / kaynak modül 7 = banka kaynaklı, 6 = çek-senet

Bakiye formülü tek satırdır: SUM(CASE WHEN SIGN = 0 THEN AMOUNT ELSE -AMOUNT END). Aşağıdaki tüm sorgular bu deseni kullanır.

1. Hesap listesi ve bakiye

SELECT A.CODE, A.DEFINITION_, A.CURRENCY,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS bakiye,
       COUNT(L.LOGICALREF) AS hareket_sayisi
FROM BANKACC A
LEFT JOIN BNFLINE L ON L.BNACCREF = A.LOGICALREF AND L.CANCELLED = 0
WHERE A.ACTIVE = 0
GROUP BY A.CODE, A.DEFINITION_, A.CURRENCY
ORDER BY bakiye DESC;

Bu raporu SQL yazmadan, Türkçe sorarak alın: Logo raporlama

ACTIVE = 0 aktif hesap demektir; 1 yazarsanız pasif hesapları listelersiniz. CANCELLED filtresi JOIN koşulunda olduğu için hiç hareketi olmayan hesap da listede kalır ve bakiyesi NULL döner; ekranda 0 göstermek istiyorsanız ISNULL(..., 0) ekleyin.

2. Tek hesabın giriş, çıkış ve son hareketi

SELECT A.CODE, A.DEFINITION_,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE 0 END) AS toplam_giris,
       SUM(CASE WHEN L.SIGN = 1 THEN L.AMOUNT ELSE 0 END) AS toplam_cikis,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS bakiye,
       MAX(L.DATE_) AS son_hareket,
       COUNT(L.LOGICALREF) AS hareket_sayisi
FROM BANKACC A
LEFT JOIN BNFLINE L ON L.BNACCREF = A.LOGICALREF AND L.CANCELLED = 0
WHERE A.CODE = 'ZIRAAT-TL'
GROUP BY A.CODE, A.DEFINITION_;

Burada 'ZIRAAT-TL' yerine kendi hesap kodunuzu yazın. MAX(DATE_) son hareket tarihini verir; hesap uzun süredir hareket görmüyorsa bu alan eski bir tarih döner ve mutabakat kontrolünde ilk bakılacak sinyaldir.

3. Hesap ekstresi: yürüyen bakiye

Ekstrede her satırın yanında o güne kadarki bakiyeyi görmek istiyorsanız pencere fonksiyonu kullanın. Sıralama DATE_ ve LOGICALREF çiftiyle yapılmalı; aynı gün içindeki hareketlerin sırası ancak LOGICALREF ile sabitlenir.

DECLARE @hesap nvarchar(50) = 'ZIRAAT-TL';

SELECT L.DATE_, L.TRCODE,
       CASE WHEN L.SIGN = 0 THEN 'giris' ELSE 'cikis' END AS yon,
       L.AMOUNT,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END)
           OVER (ORDER BY L.DATE_, L.LOGICALREF
                 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS yuruyen_bakiye
FROM BNFLINE L
JOIN BANKACC A ON A.LOGICALREF = L.BNACCREF
WHERE A.CODE = @hesap
  AND L.CANCELLED = 0
ORDER BY L.DATE_, L.LOGICALREF;

Dikkat: yürüyen bakiye, filtrelenmiş küme üzerinde hesaplanır. Tarih aralığı eklerseniz bakiye o aralığın başından itibaren birikir, hesabın açılışından değil. Açılıştan birikim istiyorsanız tarih filtresini alt sorguya taşıyıp dışarıda filtreleyin.

4. Döviz hesapta bakiye

Döviz hesabın bakiyesi AMOUNT ile değil TRNET ile toplanır. AMOUNT yerel (TL) karşılığıdır ve her satırda farklı kurla çevrildiği için TL toplamı ile döviz toplamı aynı şeyi anlatmaz.

SELECT A.CODE, A.DEFINITION_, A.CURRENCY,
       SUM(CASE WHEN L.SIGN = 0 THEN L.TRNET ELSE -L.TRNET END) AS doviz_bakiye,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS yerel_bakiye
FROM BANKACC A
JOIN BNFLINE L ON L.BNACCREF = A.LOGICALREF AND L.CANCELLED = 0
WHERE A.ACTIVE = 0 AND L.TRCURR <> 0
GROUP BY A.CODE, A.DEFINITION_, A.CURRENCY
ORDER BY doviz_bakiye DESC;

TRCURR = 0 TL hareketleri işaret eder; döviz kırılımı isterken bu koşulu koymayı unutmayın. Kur bilgisi TRRATE kolonundadır.

5. Aylık banka nakit akışı

SELECT YEAR(L.DATE_) AS yil, MONTH(L.DATE_) AS ay,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE 0 END) AS giris,
       SUM(CASE WHEN L.SIGN = 1 THEN L.AMOUNT ELSE 0 END) AS cikis,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS net
FROM BNFLINE L
JOIN BANKACC A ON A.LOGICALREF = L.BNACCREF
WHERE L.CANCELLED = 0 AND A.ACTIVE = 0
GROUP BY YEAR(L.DATE_), MONTH(L.DATE_)
ORDER BY yil DESC, ay DESC;

YEAR() ve MONTH() yalnızca datetime kolonla çalışır; DATE_ datetime olduğu için burada sorun yok. Aynı deseni int bir kolona uygularsanız "Arithmetic overflow" (8115) hatası alırsınız. Cari tarafındaki bakiye mantığını Logo stok ve cari bakiye SQL yazısında ayrıca anlattık.

6. Havale kimden geldi: cari kırılımı

SELECT C.CODE AS cari_kod, C.DEFINITION_ AS cari_ad,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS net_tutar,
       COUNT(*) AS hareket_adedi
FROM BNFLINE L
JOIN CLCARD C ON C.LOGICALREF = L.CLIENTREF
JOIN BANKACC A ON A.LOGICALREF = L.BNACCREF
WHERE L.CANCELLED = 0 AND A.CODE = 'ZIRAAT-TL'
GROUP BY C.CODE, C.DEFINITION_
ORDER BY net_tutar DESC;

CLIENTREF boş (0) olan satırlar cariye bağlanamaz, bu yüzden JOIN'de görünmez. Banka içi virmanlarda ve masraf satırlarında bu alanın boş olması normaldir; kalan farkı fiş açıklamasından takip etmek gerekir.

7. Fiş no ve hareket türü dağılımı

SELECT F.FICHENO, F.TRCODE AS fis_trcode,
       L.DATE_, L.SIGN, L.AMOUNT, L.TRCURR, L.TRNET
FROM BNFLINE L
LEFT JOIN BNFICHE F ON F.LOGICALREF = L.SOURCEFREF
JOIN BANKACC A ON A.LOGICALREF = L.BNACCREF
WHERE L.CANCELLED = 0 AND A.CODE = 'ZIRAAT-TL'
ORDER BY L.DATE_ DESC, L.LOGICALREF DESC;

Fiş başlığında FICHENO ve TRCODE güvenilir alanlardır; hareketin kendi türünü ise satırdaki TRCODE verir, ikisini karıştırmayın.

Hareket türlerinin dağılımını bir kez görmek, raporun doğruluğunu teyit etmenin en hızlı yoludur:

SELECT L.TRCODE, L.MODULENR, COUNT(*) AS hareket_adedi,
       SUM(CASE WHEN L.SIGN = 0 THEN L.AMOUNT ELSE -L.AMOUNT END) AS net_tutar
FROM BNFLINE L
WHERE L.CANCELLED = 0
GROUP BY L.TRCODE, L.MODULENR
ORDER BY hareket_adedi DESC;

MODULENR = 7 banka kaynaklı, 6 çek-senet kaynaklı hareketleri gösterir. Kendi verinizdeki dağılıma bakmadan "şu TRCODE havale, şu TRCODE masraf" diye kesin konuşmayın; kuruluma göre türler farklı işaretlenebilir. Hazır sorgu kalıpları için Logo hazır SQL sorguları listesine de bakabilirsiniz.

Sık yapılan hatalar

  • Hesap bağını BANKACCREF diye yazmak. Kolon adı BNACCREF ve karşılığı BANKACC.LOGICALREF.
  • Bakiyeyi SUM(AMOUNT) ile almak. Yön bilgisi SIGN kolonundadır: 0 borç (giriş), 1 alacak (çıkış).
  • CANCELLED = 0 filtresini unutmak; iptal edilmiş fiş satırları bakiyeyi şişirir.
  • Döviz hesapta döviz bakiyesini AMOUNT ile toplamak. Döviz tutarı TRNET, yerel karşılığı AMOUNT.
  • BANKACC.ACTIVE = 1 yazarak aktif hesapları dışlamak. Logo'da aktif kart ACTIVE = 0 demektir.
  • Bakiyeyi BNTOTFIL gibi toplam tablolarından okumak. Bu tablolar trigger ile bakımlıdır, elle yazılmaz ve bazı kurulumlarda geride kalabilir; rapor için güvenilir kaynak BNFLINE.
  • Tabloları CODE üzerinden birleştirmek. Tüm bağlar LOGICALREF ile kurulur.
  • Fiş başlığında var olmayan bir kolonu (örneğin DOCODE) sorgulamak. BNFICHE'de emin olmadığınız alanı hiç yazmayın.
  • Tarih filtresini int bir kolona uygulamak; tarih işlemleri yalnızca DATE_ gibi datetime kolonlarla yapılır.

Sık sorulanlar

Bakiye neden eksi çıkıyor? SIGN yönünü ters yorumluyorsunuz. SIGN = 0 para girişi, 1 para çıkışıdır; formülü SUM(CASE WHEN SIGN = 0 THEN AMOUNT ELSE -AMOUNT END) olarak kurun. Bir hesapta sonuç eksi ise ya açılış bakiyesi hiç hareket olarak girilmemiştir ya da çıkışlar girişlerden fazladır.

Hesap kodu yerine hesap adıyla filtreleyebilir miyim? Evet, BANKACC.DEFINITION_ üzerinden LIKE ile arayabilirsiniz. Ancak tanım alanı serbest metindir ve kullanıcılar tarafından değiştirilebilir; raporu CODE üzerine kurmak daha güvenlidir.

Ekstrede aynı günün hareketleri neden karışık geliyor? Sıralamayı yalnızca DATE_ ile yaptığınızda aynı tarihli satırların sırası garanti değildir. ORDER BY L.DATE_, L.LOGICALREF kullanın; yürüyen bakiye de aynı sıralama anahtarını kullanmalıdır.

Virman ve masraf satırları banka bakiyesine dahil mi? Evet, BNFLINE'daki her satır bakiyeye girer. Ayrı görmek istiyorsanız TRCODE ve MODULENR kırılımını kullanın, komisyon satırları için COMSTYPE alanına bakın.


Bu yedi sorguyu her ay elle güncellemek yerine Erp Asistanı'na ücretsiz kaydolun →: "geçen ayın banka hesap bakiyelerini ve giriş çıkış toplamlarını getir" diye Türkçe yazarsınız, sistem BNFLINE, SIGN ve LG öneklerine uygun çalışan SQL'i üretir; siz yalnızca sonucu kontrol edersiniz.

Bu yazıyı paylaş
Logo raporlama

Bu raporu SQL yazmadan, Türkçe sorarak 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.