Firebird CariBakiye Hesaplama Stored Procedure - Baskı Önizleme +- Delphi Can (https://www.delphican.com) +-- Forum: Veri Tabanı (https://www.delphican.com/forumdisplay.php?fid=4) +--- Forum: FireBird (https://www.delphican.com/forumdisplay.php?fid=13) +--- Konu Başlığı: Firebird CariBakiye Hesaplama Stored Procedure (/showthread.php?tid=647) |
Firebird CariBakiye Hesaplama Stored Procedure - masteryoda - 08-02-2017 Merhaba Bir müşterimin istediği üzerine yazmaya başladığım küçük çaplı ön muhasebe programında kullandığım CariBakiyeHesaplama stored procedure ü paylaşıyorum. stored procedure ler object pascal da kullandığımız procedurlere benzer fonksiyon gibi geriye değer de döndürebilirler Cariler Tablomda borc,alacak,bakiye,yerelborc,yerelalacak,yerelbakiye alanlarım var bu alanlar numeric 15,4 olarak tanımlı, firma_id (integer) alanı programda birden fazla firma tanımlayıp kullanılabiliyor firma ayracı diyebiliriz foreign key ile firmalar tablosunda ki firma_id alanına bağlı cari_id (integer) primary key olarak tanımlı. carihareket tablosunda da aynı cari_id, ve firma_id alanları var carihareket tablosuna yeni bir kayıt eklendiğinde, silindiğinde, değiştirildiğinde ilgili kaydın bağlı bulunduğu cariler tablosundada borc,alacak,bakiye.. alanlarımın güncellenmesini istiyorum bunuda SP_CBAKIYE_HESAPLA ismini verdiğim stored procedure ile yapacağız. sp de iki input parametresi tanımlıyorum gfirma_id (sp parametre olarak gelecek firma id si ) integer tanımlı. gcari_id (sp_parametre olarak cari id si) integer ibexpert kullanıyorsanız input parameters bölümünde tanımlayabilirsiniz input parametreleriniz Procedure de tanımladığım değişkenler yine ibexpert de variables kısmında tanımlayabiliyorsunuz DMN_PARATUTAR benim numeric 15,4 olarak tanımladığım domain siz numeric 15,4 olarak yada double kullanıyorsanız double seçebilirsiniz TBORC DMN_PARATUTAR = 0; TALACAK DMN_PARATUTAR = 0; TBAKIYE DMN_PARATUTAR = 0; TYEREL_BORC DMN_PARATUTAR = 0; TYEREL_ALACAK DMN_PARATUTAR = 0; TYEREL_BAKIYE DMN_PARATUTAR = 0; KAYIT_SAYISI integer; // gcari_id parametresi ile cariharekete bulunan kayıt sayısı SELECT COUNT(*) FROM carihareket WHERE carihareket.cari_id = :gcari_id INTO :kayit_sayisi; // kayit_sayisi değişkenine tablodaki kayıt sayısını aktardık if (kayit_sayisi>0) then // kayıt var ise begin select sum (carihareket.borc), sum (carihareket.alacak), sum (carihareket.yerelborc), sum (carihareket.yerelalacak) from carihareket where 1=1 and carihareket.firma_id=:gfirma_id and carihareket.cari_id=:gcari_id into // select sıramızla aynı olacak şekilde dönen değerleri değişkenlerimize aktarıyoruz :tborc, :talacak, :tyerel_borc, :tyerel_alacak; if (tborc is null) then tborc=0; // her ihtimale karşı null ise 0 atıyoruz if (talacak is null) then talacak=0; if (tyerel_borc is null) then tyerel_borc=0; if (tyerel_alacak is null) then tyerel_alacak=0; tbakiye=tborc-talacak; // toplam borçtan toplam alacağı çıkarıp tbakiye değişkenine aktarıyoruz tyerel_bakiye=tyerel_borc-tyerel_alacak; if (tbakiye is null) then tbakiye=0; if (tyerel_bakiye is null) then tyerel_bakiye=0; // değişkenlerimize atadığımız değerleri cariler tablosunda ki ilgili alanlarımıza update ediyoruz update cariler set cariler.borc=:tborc, cariler.alacak=:talacak, cariler.bakiye=:tbakiye, cariler.yerelborc=:tyerel_borc, cariler.yerelalacak=:tyerel_alacak, cariler.yerelbakiye=:tyerel_bakiye where 1=1 and cariler.firma_id=:gfirma_id and cariler.cari_id=:gcari_id; end if (kayit_sayisi=0) then // hiç kayıt yok ise örnek carihareketi son kaydı sildik alanlarımıza 0 değeri atıyoruz begin update cariler set cariler.borc=0, cariler.alacak=0, cariler.bakiye=0, cariler.yerelborc=0, cariler.yerelalacak=0, cariler.yerelbakiye=0 where 1=1 and cariler.firma_id=:gfirma_id and cariler.cari_id=:gcari_id; end Procedürümüzü delphi tarafında query nesnesi ile de parametreleri vererek çalıştırabiliriz EXECUTE PROCEDURE SP_CBAKIYE_HESAPLA(1, 1)trigerla After insert trigerına execute procedure sp_cbakiye_hesapla(new.firma_id,new.cari_id);After delete trigerına execute procedure sp_cbakiye_hesapla(old.firma_id,old.cari_id);after update trigerına execute procedure sp_cbakiye_hesapla(old.firma_id,old.cari_id);aslında update trigerında kontrolü yapmamız daha mantıklı borc,alacak v.s alanlar değişmediğinde örnek sadece açıklama alanı değişti yine çalışaktır gereksiz yük cariler tablonuzda hiç borç,alacak v.s kullanmayada bilirsiniz benim yapı denormalize bir yapı buradaki kodlarda bu yapıya göre. son olarak ddl kodları SET TERM ^ ; create or alter procedure SP_CBAKIYE_HESAPLA ( GFIRMA_ID integer not null, GCARI_ID integer not null) as declare variable TBORC DMN_PARATUTAR = 0; declare variable TALACAK DMN_PARATUTAR = 0; declare variable TBAKIYE DMN_PARATUTAR = 0; declare variable TYEREL_BORC DMN_PARATUTAR = 0; declare variable TYEREL_ALACAK DMN_PARATUTAR = 0; declare variable TYEREL_BAKIYE DMN_PARATUTAR = 0; declare variable KAYIT_SAYISI integer; begin SELECT COUNT(*) FROM carihareket WHERE carihareket.cari_id = :gcari_id INTO :kayit_sayisi; if (kayit_sayisi>0) then begin select sum (carihareket.borc), sum (carihareket.alacak), sum (carihareket.yerelborc), sum (carihareket.yerelalacak) from carihareket where 1=1 and carihareket.firma_id=:gfirma_id and carihareket.cari_id=:gcari_id into :tborc, :talacak, :tyerel_borc, :tyerel_alacak; if (tborc is null) then tborc=0; if (talacak is null) then talacak=0; if (tyerel_borc is null) then tyerel_borc=0; if (tyerel_alacak is null) then tyerel_alacak=0; tbakiye=tborc-talacak; tyerel_bakiye=tyerel_borc-tyerel_alacak; if (tbakiye is null) then tbakiye=0; if (tyerel_bakiye is null) then tyerel_bakiye=0; update cariler set cariler.borc=:tborc, cariler.alacak=:talacak, cariler.bakiye=:tbakiye, cariler.yerelborc=:tyerel_borc, cariler.yerelalacak=:tyerel_alacak, cariler.yerelbakiye=:tyerel_bakiye where 1=1 and cariler.firma_id=:gfirma_id and cariler.cari_id=:gcari_id; end if (kayit_sayisi=0) then begin update cariler set cariler.borc=0, cariler.alacak=0, cariler.bakiye=0, cariler.yerelborc=0, cariler.yerelalacak=0, cariler.yerelbakiye=0 where 1=1 and cariler.firma_id=:gfirma_id and cariler.cari_id=:gcari_id; end END ^ SET TERM ; ^ /* Following GRANT statements are generated automatically */ GRANT SELECT ON CARIHAREKET TO PROCEDURE SP_CBAKIYE_HESAPLA; GRANT SELECT,UPDATE ON CARILER TO PROCEDURE SP_CBAKIYE_HESAPLA; /* Existing privileges on this procedure */ GRANT EXECUTE ON PROCEDURE SP_CBAKIYE_HESAPLA TO SYSDBA; Firebird CariBakiye Hesaplama Stored Procedure - SimaWB - 08-02-2017 Paylaşım için teşekkürler. Emeğinize sağlık. Cvp: Firebird CariBakiye Hesaplama Stored Procedure - TescilsizUzman - 08-02-2017 Merhaba, Değerli katkılarınızdan dolayı teşekkür ederim. Cvp: Firebird CariBakiye Hesaplama Stored Procedure - esistem - 08-02-2017 Merhaba, Değerli katkınız için teşekkürler. Programı yeni yazmaya başlamışsınız o yüzden naçizane bir önerim olacak. Bu yapıyı EticariPlus u ilk yazdığımda kullanmıştım fakat oldukça hantal kalıyor. Zira Cari_Hareket tablosunda her insert, update veya delete işleminde trigger tetikleyip, seçili cari hesap için bütün hareketlerde her defasında SUM alıp Cari tablosunda Borc, Alacak alanlarını güncelliyorsunuz. Bunun yerine şöyle basit bir olay kullanabilirsiniz. Cari tablosuna yeni kayıt açıldığında, Borc ve Alacak varsayılan 0 (Sıfır) girilir. Cari_Hareket tablosunda da Borc ve Alacak alanları zaten var, Daha sonra, Cari_Hareket_AI (After Insert) UPDATE Cari SET Borc = Borc + New.Borc, Alacak = Alacak + New.Alacak WHERE id = New.Cari_id; Cari_Hareket_AU (After Update) UPDATE Cari SET Borc = Borc - Old.Borc, Alacak = Alacak - Old.Alacak WHERE id = Old.Cari_id; UPDATE Cari SET Borc = Borc + New.Borc, Alacak = Alacak + New.Alacak WHERE id = New.Cari_id; Cari_Hareket_AD (After Delete) UPDATE Cari SET Borc = Borc - Old.Borc, Alacak = Alacak - Old.Alacak WHERE id = Old.Cari_id; şeklinde çok çok daha hızlı çalışması sağlanabilir. Firebird CariBakiye Hesaplama Stored Procedure - masteryoda - 08-02-2017 @esistem hocam bir defasında aynen sizin yaptığınız şekilde yaptım 2-3 yıl oluyor herhalde , yanlış hesaplama yapıyormu diye testler yapmıştım bir yerde yanlış hesaplamıştı o case i hatırlamıyorum (çok kurcalamıştım) belkide ozamanki kodlarım tam sizin ki gibi değildir yine bunu da örnek bir yerde kullanıp test ederim. |