VBA: Kombine Stok Değerleme Yöntemleri (FIFO, LIFO, Ağırlıklı Ortalama, Hareketli Ortalama)

 Merhaba Ziyaretçi !

    Yaklaşık üç yıl öncesinden beri aklımda olan ancak bir türlü başlayamadığım kombine stok değerleme yöntemleri projesini 2021 Mayıs ayında başlayıp bitirmiştim. O zamandan beri de bir üşengençlik ki, şimdi yayınlayabildim.

Excel platformlarında bu konuda çok şeyler yazıldı, çizildi. Ancak bu proje diğerlerinde farklıdır. Farklı olmasını sağlayan üç önemli özelliği vardır:

  • Bir değil, birden fazla yöntem vardır,
  • Bu yöntemler yatay karşılaştırılabilir dizayndadır,
  • Kaynak şablona bağlı değildir. Yani; Excel, Text, Csv, Recordset vs. olabilir.

    Bu proje ile stok değerleme yöntemlerine göre hesaplanan maliyetleri yan yana karşılaştırabilir, satır hareketi bazında karlılığı görebilir veya hangi stok değerleme yöntemini kullanmanız gerektiği konusunda size ışık tutabilir.

Projenin teknik boyutuna baktığınızda üç tür örnek hazırladığımı göreceksiniz. Bunlar;

  • Emtia alım satımı, 
  • Döviz alım satımı, 
  • İmalat giriş çıkışları. 

Hangi örneği çalıştırısanız çalıştırın ekranınıza üç tür rapor dizaynı basacaktır. Bunlar;

  1. Detaylı : Satır hareketi bazında rapor,
  2. Özet : Satır hareketlerinin dikey toplamları,
  3. Kalanlar : Fifo & Lifo için kalan stok hareketlerinin listesi.

Projenin VBA ayağına geldiğimizde kullanmanız gereken üç metod mevcuttur.

  1. BeginStock : Veritabanına aktarmak istediğiniz stok kodu/adıdır. AddRecord çağrılmadan önce kullanılır. Her yeni stok kodu eklemek istediğinizde bu metodu çağırın. 32 bit sayı (index) döndürür.
  2. AddRecord : Stok giriş/çıkış hareketlerini bu metod ile veritabanına aktarısınız.
  3. Run : Hesaplama işlemini başlatır ve üç parametresi vardır:
  •  printReportToScreen : Run metodu bittiğinde hesapların ekrana basılıp basılmayacağı bildirilir. (Default: True)
  • calcAvgWeightPerMonth : Üç ayı kapsayan bir liste eklediyseniz, ağırlıklı ortalamada üç aylık tek bir ortalama yerine her ay için ayrı ortalamalar hesaplanır. (Default: False)
  •  includeFifo_LifoDetailToReport : "Detaylı" rapordaki çıkış satırlarının hemen altına FIFO ve LIFO giriş bilgilerinin iliştirilip iliştirilmeyeceği bildirilir. (Default: False)

 

Raporların bazı ekran görüntüleri:


 

Firebird SQL Server Database DDL Script :


/**************************************
    Author : Zeki Gürsoy
    Date   : 08/03/2022
    Mail   : gursoyzeki@gmail.com
***************************************/
/**************************************/
/*************** TABLE ****************/
/**************************************/
CREATE TABLE TBL_FIFODETAY
(
  ID BIGINT,
  IDGIRIS BIGINT,
  CMIKTAR DECIMAL(18,4),
  CMALIYET DECIMAL(18,2)
);

CREATE TABLE TBL_LIFODETAY
(
  ID BIGINT,
  IDGIRIS BIGINT,
  CMIKTAR DECIMAL(18,4),
  CMALIYET DECIMAL(18,2)
);

CREATE TABLE TBL_AGIRLIKLI_PARENTDETAY
(
  STOKID BIGINT,
  AY_INDEX INTEGER,
  LAST_ID BIGINT,
  GMIKTAR DECIMAL(18,4),
  CMIKTAR DECIMAL(18,4),
  GTUTAR DECIMAL(18,2) DEFAULT 0
);

CREATE TABLE TBL_TUMGIRISLER
(
  ID BIGINT,
  STOKID INTEGER,
  TARIH DATE,
  FIYAT DECIMAL(18,6) DEFAULT 0,
  FIFOKALANMIKTAR DECIMAL(18,4),
  FIFOKALANTUTAR DECIMAL(18,2) DEFAULT 0,
  LIFOKALANMIKTAR DECIMAL(18,4),
  LIFOKALANTUTAR DECIMAL(18,2) DEFAULT 0
);

CREATE TABLE TBL_TUMKAYITLAR
(
  ID BIGINT GENERATED BY DEFAULT AS IDENTITY  NOT NULL,
  STOKID INTEGER,
  STOKADI VARCHAR(80),
  GC SMALLINT,
  TARIH DATE,
  AY_INDEX INTEGER,
  EVRAKNO VARCHAR(30),
  ACIKLAMA VARCHAR(80),
  MIKTAR DECIMAL(18,4),
  FIYAT DECIMAL(18,6),
  TUTAR DECIMAL(18,2),
  ORT_AGIRLIKLI_MALIYET DECIMAL(18,2),
  ORT_AGIRLIKLI_KALAN_TUTAR DECIMAL(18,2),
  ORT_HAREKETLI_MALIYET DECIMAL(18,2),
  ORT_HAREKETLI_KALAN_TUTAR DECIMAL(18,2),
  FIFO_MALIYET DECIMAL(18,2),
  LIFO_MALIYET DECIMAL(18,2)
);

/*
CREATE TABLE TMP EXTERNAL 'temptable.txt'
(
  STOKID CHAR(5),
  STOKADI CHAR(80),
  GC CHAR(1),
  TARIH CHAR(10),
  EVRAKNO CHAR(30),
  ACIKLAMA CHAR(80),
  MIKTAR CHAR(20),
  FIYAT CHAR(22),
  TUTAR CHAR(18)
);
*/

CREATE TABLE TMP EXTERNAL 'temptable.txt'
(
  STOKID INTEGER,
  STOKADI CHAR(80),
  GC SMALLINT,
  TARIH DATE,
  EVRAKNO CHAR(30),
  ACIKLAMA CHAR(80),
  MIKTAR DECIMAL(18,4),
  FIYAT DECIMAL(18,6),
  TUTAR DECIMAL(18,2)
);

/**************************************/
/**************** VIEW ****************/
/**************************************/
CREATE VIEW RPT_DETAYLI (STOK_ID, STOK_ADI, GC, TARIH, EVRAK_NO, ACIKLAMA,
   MIKTAR, FIYAT, TUTAR, ORT_AGIRLIKLI_MALIYET, ORT_HAREKETLI_MALIYET,
   FIFO_MALIYET, LIFO_MALIYET, KALAN_MIKTAR, ORT_AGIRLIKLI_KALAN_TUTAR,
   ORT_HAREKETLI_KALAN_TUTAR, FIFO_KALAN_TUTAR, LIFO_KALAN_TUTAR)
AS
SELECT STOKID, STOKADI, GC, TARIH, EVRAKNO, ACIKLAMA, MIKTAR, FIYAT, TUTAR, ORT_AGIRLIKLI_MALIYET, ORT_HAREKETLI_MALIYET, FIFO_MALIYET, LIFO_MALIYET,
       SUM(DECODE(GC, 1, MIKTAR, -MIKTAR)) OVER (PARTITION BY STOKID ORDER BY ID) KALAN_MIKTAR,       
       ORT_AGIRLIKLI_KALAN_TUTAR, ORT_HAREKETLI_KALAN_TUTAR,       
       SUM(DECODE(GC, 1, TUTAR, -FIFO_MALIYET)) OVER (PARTITION BY STOKID ORDER BY ID) FIFO_KALAN_TUTAR,
       SUM(DECODE(GC, 1, TUTAR, -LIFO_MALIYET)) OVER (PARTITION BY STOKID ORDER BY ID) LIFO_KALAN_TUTAR
FROM TBL_TUMKAYITLAR;

CREATE VIEW RPT_FIFO_KALANLAR (STOK_ID, STOK_ADI, TARIH, EVRAK_NO, ACIKLAMA,
   MIKTAR, FIYAT, TUTAR, FIFO_KALAN_MIKTAR, FIFO_KALAN_TUTAR)
AS
SELECT tg.STOKID, tk.STOKADI, tg.TARIH, tk.EVRAKNO, tk.ACIKLAMA, tk.MIKTAR, tg.FIYAT, tk.TUTAR, tg.FIFOKALANMIKTAR, tg.FIFOKALANTUTAR
FROM TBL_TUMGIRISLER tg
   INNER JOIN TBL_TUMKAYITLAR tk ON tk.ID = tg.ID
WHERE tg.FIFOKALANMIKTAR > 0;

CREATE VIEW RPT_LIFO_KALANLAR (STOK_ID, STOK_ADI, TARIH, EVRAK_NO, ACIKLAMA,
   MIKTAR, FIYAT, TUTAR, LIFO_KALAN_MIKTAR, LIFO_KALAN_TUTAR)
AS
SELECT tg.STOKID, tk.STOKADI, tg.TARIH, tk.EVRAKNO, tk.ACIKLAMA, tk.MIKTAR, tg.FIYAT, tk.TUTAR, tg.LIFOKALANMIKTAR, tg.LIFOKALANTUTAR
FROM TBL_TUMGIRISLER tg
   INNER JOIN TBL_TUMKAYITLAR tk ON tk.ID = tg.ID
WHERE tg.LIFOKALANMIKTAR > 0;

CREATE VIEW RPT_OZET (STOK_ID, STOK_ADI, GIREN_MIKTAR, GIREN_TUTAR,
   CIKAN_MIKTAR, CIKAN_TUTAR, ORT_AGIRLIKLI_MALIYET, ORT_HAREKETLI_MALIYET,
   FIFO_MALIYET, LIFO_MALIYET, KALAN_MIKTAR, ORT_AGIRLIKLI_KALAN_TUTAR,
   ORT_HAREKETLI_KALAN_TUTAR, FIFO_KALAN_TUTAR, LIFO_KALAN_TUTAR)
AS
SELECT D.STOKID, D.STOKADI, D.GIREN_MIKTAR, D.GIREN_TUTAR, D.CIKAN_MIKTAR, D.CIKAN_TUTAR,
   D.ORT_AGIRLIKLI_MALIYET, D.ORT_HAREKETLI_MALIYET, D.FIFO_MALIYET, D.LIFO_MALIYET,
   D.GIREN_MIKTAR - D.CIKAN_MIKTAR KALAN_MIKTAR,
   D.GIREN_TUTAR - D.ORT_AGIRLIKLI_MALIYET ORT_AGIRLIKLI_KALAN_TUTAR,
   D.GIREN_TUTAR - D.ORT_HAREKETLI_MALIYET ORT_HAREKETLI_KALAN_TUTAR,
   D.GIREN_TUTAR - D.FIFO_MALIYET FIFO_KALAN_TUTAR,
   D.GIREN_TUTAR - D.LIFO_MALIYET LIFO_KALAN_TUTAR
FROM(
   SELECT STOKID, STOKADI,      
      SUM(DECODE(GC, 1, MIKTAR, 0)) GIREN_MIKTAR,
      SUM(DECODE(GC, 1, TUTAR, 0)) GIREN_TUTAR,
      SUM(DECODE(GC, 2, MIKTAR, 0)) CIKAN_MIKTAR,
      SUM(DECODE(GC, 2, TUTAR, 0)) CIKAN_TUTAR,
      SUM(ORT_AGIRLIKLI_MALIYET) ORT_AGIRLIKLI_MALIYET,
      SUM(ORT_HAREKETLI_MALIYET) ORT_HAREKETLI_MALIYET,
      SUM(FIFO_MALIYET) FIFO_MALIYET,
      SUM(LIFO_MALIYET) LIFO_MALIYET
   FROM TBL_TUMKAYITLAR
   GROUP BY STOKID, STOKADI
) D;

/**************************************/
/************** PROCEDURE *************/
/**************************************/
SET TERM ^;

CREATE PROCEDURE CMD_RECREATE_TMP (EXT_FILE VARCHAR(255))
AS
BEGIN
   EXECUTE STATEMENT 'RECREATE TABLE TMP EXTERNAL ''' || EXT_FILE || ''' (
                      STOKID INTEGER, STOKADI CHAR(80), GC SMALLINT, TARIH DATE, EVRAKNO CHAR(30),
                      ACIKLAMA CHAR(80), MIKTAR DECIMAL(18,4), FIYAT DECIMAL(18,6), TUTAR DECIMAL(18,2))';
END
^

CREATE PROCEDURE INTERNAL_AGIRLIKLI_ORTALAMA_AYLIK
AS
DECLARE TSTOKID          INTEGER;
DECLARE TAYINDEX         INTEGER;
DECLARE TID              BIGINT;
DECLARE TGIREN_MIKTAR    DECIMAL(18,4) = 0;
DECLARE TCIKAN_MIKTAR    DECIMAL(18,4) = 0;
DECLARE TGIREN_TUTAR     DECIMAL(18,2) = 0;
DECLARE TMALIYET         DECIMAL(18,2) = 0;
DECLARE DEVREDENMIKTAR   DECIMAL(18,4) = 0;
DECLARE DEVREDENTUTAR    DECIMAL(18,2) = 0;
DECLARE TOP_GIREN_MIKTAR DECIMAL(18,4) = 0;
DECLARE TOP_GIREN_TUTAR  DECIMAL(18,2) = 0;
DECLARE ORT_FIYAT        DECIMAL(18,6) = 0;
DECLARE TOP_MALIYET      DECIMAL(18,2) = 0;
DECLARE GECERLI_STOKID   INTEGER       = 1;
BEGIN
   INSERT INTO TBL_AGIRLIKLI_PARENTDETAY
   SELECT tk.STOKID, tk.AY_INDEX, MAX(tk.ID), SUM(g.MIKTAR), SUM(c.MIKTAR), SUM(g.TUTAR)
   FROM TBL_TUMKAYITLAR tk
      LEFT JOIN TBL_TUMKAYITLAR c ON c.ID = tk.ID AND c.GC = 2
      LEFT JOIN TBL_TUMKAYITLAR g ON g.ID = tk.ID AND g.GC = 1
   GROUP BY tk.STOKID, tk.AY_INDEX;
   
   FOR SELECT STOKID, AY_INDEX, LAST_ID, GMIKTAR, CMIKTAR, GTUTAR FROM TBL_AGIRLIKLI_PARENTDETAY INTO TSTOKID, TAYINDEX, TID, TGIREN_MIKTAR, TCIKAN_MIKTAR, TGIREN_TUTAR DO
   BEGIN
      IF (TSTOKID != GECERLI_STOKID) THEN
      BEGIN
         DEVREDENMIKTAR = 0;
         DEVREDENTUTAR = 0;
         GECERLI_STOKID = TSTOKID;
      END
      
      TOP_GIREN_TUTAR  = DEVREDENTUTAR  + TGIREN_TUTAR;
      TOP_GIREN_MIKTAR = DEVREDENMIKTAR + TGIREN_MIKTAR;
      ORT_FIYAT        = ROUND(TOP_GIREN_TUTAR / NULLIF(TOP_GIREN_MIKTAR, 0), 6);
      
      UPDATE TBL_TUMKAYITLAR SET ORT_AGIRLIKLI_MALIYET = ROUND(MIKTAR * :ORT_FIYAT, 2) WHERE STOKID = :TSTOKID AND AY_INDEX = :TAYINDEX AND GC = 2;      
      
      SELECT SUM(ORT_AGIRLIKLI_MALIYET) FROM TBL_TUMKAYITLAR WHERE STOKID = :TSTOKID AND AY_INDEX = :TAYINDEX AND GC = 2 INTO TOP_MALIYET;
      
      DEVREDENTUTAR  = TOP_GIREN_TUTAR  - TOP_MALIYET;
      DEVREDENMIKTAR = TOP_GIREN_MIKTAR - TCIKAN_MIKTAR;      
      
      UPDATE TBL_TUMKAYITLAR SET ORT_AGIRLIKLI_KALAN_TUTAR = :DEVREDENTUTAR WHERE ID = :TID;
   END
END
^

CREATE PROCEDURE INTERNAL_AGIRLIKLI_ORTALAMA_GENEL
AS
DECLARE LASTID           BIGINT;
DECLARE STOKID           INTEGER;
DECLARE TOP_CIKAN_MIKTAR DECIMAL(18,4);
DECLARE TOP_GIREN_MIKTAR DECIMAL(18,4);
DECLARE TOP_GIREN_TUTAR  DECIMAL(18,2);
DECLARE ORT_FIYAT        DECIMAL(18,6);
DECLARE TOP_MALIYET      DECIMAL(18,2);
BEGIN
   INSERT INTO TBL_AGIRLIKLI_PARENTDETAY
   SELECT tk.STOKID, 0, MAX(tk.ID), SUM(g.MIKTAR), SUM(c.MIKTAR), SUM(g.TUTAR)
   FROM TBL_TUMKAYITLAR tk
      LEFT JOIN TBL_TUMKAYITLAR c ON c.ID = tk.ID AND c.GC = 2
      LEFT JOIN TBL_TUMKAYITLAR g ON g.ID = tk.ID AND g.GC = 1
   GROUP BY tk.STOKID;
   
   FOR SELECT STOKID, LAST_ID, GMIKTAR, CMIKTAR, GTUTAR FROM TBL_AGIRLIKLI_PARENTDETAY
       INTO STOKID, LASTID, TOP_GIREN_MIKTAR, TOP_CIKAN_MIKTAR, TOP_GIREN_TUTAR DO
   BEGIN        
      ORT_FIYAT = ROUND(TOP_GIREN_TUTAR / NULLIF(TOP_GIREN_MIKTAR, 0), 6);  
      
      SELECT SUM(ROUND(MIKTAR * :ORT_FIYAT, 2)) FROM TBL_TUMKAYITLAR WHERE STOKID = :STOKID AND GC = 2 INTO TOP_MALIYET;
      
      UPDATE TBL_TUMKAYITLAR SET ORT_AGIRLIKLI_MALIYET = ROUND(MIKTAR * :ORT_FIYAT, 2) WHERE STOKID = :STOKID AND GC = 2;
      
      UPDATE TBL_TUMKAYITLAR SET ORT_AGIRLIKLI_KALAN_TUTAR = :TOP_GIREN_TUTAR - :TOP_MALIYET WHERE ID = :LASTID;
   END
END
^

CREATE PROCEDURE INTERNAL_HAREKETLI_ORTALAMA
AS
DECLARE OUTER_STOKID     INTEGER;
DECLARE HAREKETLI_MIKTAR DECIMAL(18,4);
DECLARE HAREKETLI_TUTAR  DECIMAL(18,2);
DECLARE INNER_GC         SMALLINT;
DECLARE INNER_MIKTAR     DECIMAL(18,4);
DECLARE INNER_TUTAR      DECIMAL(18,2);
DECLARE ORT_FIYAT        DECIMAL(18,6);
DECLARE MALIYET          DECIMAL(18,2);
BEGIN
   FOR SELECT T1.STOKID FROM TBL_TUMKAYITLAR T1 GROUP BY T1.STOKID INTO OUTER_STOKID DO
   BEGIN
      HAREKETLI_MIKTAR = 0;
      HAREKETLI_TUTAR  = 0;
      
      FOR SELECT T2.GC, T2.MIKTAR, T2.TUTAR FROM TBL_TUMKAYITLAR T2 WHERE T2.STOKID = :OUTER_STOKID INTO INNER_GC, INNER_MIKTAR, INNER_TUTAR AS CURSOR CUR DO
      BEGIN
         IF (INNER_GC = 1) THEN
         BEGIN
            HAREKETLI_MIKTAR = HAREKETLI_MIKTAR + INNER_MIKTAR;
            HAREKETLI_TUTAR  = HAREKETLI_TUTAR  + INNER_TUTAR;
            
            UPDATE TBL_TUMKAYITLAR SET ORT_HAREKETLI_KALAN_TUTAR = :HAREKETLI_TUTAR WHERE CURRENT OF CUR;            
         END ELSE
         BEGIN
            ORT_FIYAT = ROUND(HAREKETLI_TUTAR / NULLIF(HAREKETLI_MIKTAR, 0), 6);
            MALIYET   = ROUND(INNER_MIKTAR * ORT_FIYAT, 2);
            
            UPDATE TBL_TUMKAYITLAR SET ORT_HAREKETLI_MALIYET = :MALIYET, ORT_HAREKETLI_KALAN_TUTAR = :HAREKETLI_TUTAR - :MALIYET WHERE CURRENT OF CUR;
                                    
            HAREKETLI_MIKTAR = HAREKETLI_MIKTAR - INNER_MIKTAR;
            HAREKETLI_TUTAR  = HAREKETLI_TUTAR  - MALIYET;
         END
      END
   END
END
^

CREATE PROCEDURE INTERNAL_FIFO
AS
DECLARE CID         BIGINT;
DECLARE CSTKID      INTEGER;
DECLARE CTARIH      DATE;
DECLARE CMIKTAR     DECIMAL(18,4);
DECLARE GID         BIGINT;
DECLARE GFIYAT      DECIMAL(18,6);
DECLARE FGMIKTAR    DECIMAL(18,4);
DECLARE FGTUTAR     DECIMAL(18,2);
DECLARE KALANMIKTAR DECIMAL(18,4);
DECLARE TMPTUTAR    DECIMAL(18,2);
BEGIN   
   FOR SELECT ID, STOKID, TARIH, MIKTAR FROM TBL_TUMKAYITLAR WHERE GC = 2 INTO CID, CSTKID, CTARIH, CMIKTAR DO
   BEGIN
      KALANMIKTAR = CMIKTAR;
      
      FOR SELECT ID, FIYAT, FIFOKALANMIKTAR, FIFOKALANTUTAR FROM TBL_TUMGIRISLER WHERE STOKID = :CSTKID And TARIH <= :CTARIH And FIFOKALANMIKTAR > 0
          INTO GID, GFIYAT, FGMIKTAR, FGTUTAR AS CURSOR CUR DO
      BEGIN
         IF (KALANMIKTAR < FGMIKTAR) THEN
         BEGIN
            TMPTUTAR = ROUND(KALANMIKTAR * GFIYAT, 2);
                      
            INSERT INTO TBL_FIFODETAY VALUES(:CID, :GID, :KALANMIKTAR, :TMPTUTAR);    
                    
            UPDATE TBL_TUMGIRISLER SET FIFOKALANMIKTAR = :FGMIKTAR - :KALANMIKTAR, FIFOKALANTUTAR = :FGTUTAR - :TMPTUTAR WHERE CURRENT OF CUR;
            
            LEAVE;
         END ELSE
         BEGIN
            INSERT INTO TBL_FIFODETAY VALUES(:CID, :GID, :FGMIKTAR, :FGTUTAR);
            
            UPDATE TBL_TUMGIRISLER SET FIFOKALANMIKTAR = 0, FIFOKALANTUTAR = 0 WHERE CURRENT OF CUR;
            
            KALANMIKTAR = KALANMIKTAR - FGMIKTAR;      
             
            IF (KALANMIKTAR = 0) THEN LEAVE;
         END
      END
   END
   
   MERGE INTO TBL_TUMKAYITLAR T USING (SELECT ID, SUM(CMALIYET) MALIYET FROM TBL_FIFODETAY GROUP BY ID) F ON F.ID = T.ID
      WHEN MATCHED THEN UPDATE SET T.FIFO_MALIYET = F.MALIYET;
END
^

CREATE PROCEDURE INTERNAL_LIFO
AS
DECLARE CID         BIGINT;
DECLARE CSTKID      INTEGER;
DECLARE CTARIH      DATE;
DECLARE CMIKTAR     DECIMAL(18,4);
DECLARE GID         BIGINT;
DECLARE LGMIKTAR    DECIMAL(18,4);
DECLARE GFIYAT      DECIMAL(18,6);
DECLARE LGTUTAR     DECIMAL(18,2);
DECLARE KALANMIKTAR DECIMAL(18,4);
DECLARE TMPTUTAR    DECIMAL(18,2);
DECLARE CUR SCROLL CURSOR FOR(SELECT ID, FIYAT, LIFOKALANMIKTAR, LIFOKALANTUTAR FROM TBL_TUMGIRISLER
                              WHERE STOKID = :CSTKID And TARIH <= :CTARIH And LIFOKALANMIKTAR > 0);
BEGIN
   FOR SELECT ID, STOKID, TARIH, MIKTAR FROM TBL_TUMKAYITLAR WHERE GC = 2 INTO CID, CSTKID, CTARIH, CMIKTAR DO
   BEGIN
      KALANMIKTAR = CMIKTAR;
      
      OPEN CUR;
      
      FETCH LAST FROM CUR INTO GID, GFIYAT, LGMIKTAR, LGTUTAR;
      
      WHILE (ROW_COUNT > 0) DO
      BEGIN               
         IF (KALANMIKTAR < LGMIKTAR) THEN
         BEGIN
            TMPTUTAR = ROUND(KALANMIKTAR * GFIYAT, 2);   
                     
            INSERT INTO TBL_LIFODETAY VALUES(:CID, :GID, :KALANMIKTAR, :TMPTUTAR);   
                     
            UPDATE TBL_TUMGIRISLER SET LIFOKALANMIKTAR = :LGMIKTAR - :KALANMIKTAR, LIFOKALANTUTAR = :LGTUTAR - :TMPTUTAR WHERE CURRENT OF CUR;            
            
            LEAVE;
         END ELSE
         BEGIN
            INSERT INTO TBL_LIFODETAY VALUES(:CID, :GID, :LGMIKTAR, :LGTUTAR);
            
            UPDATE TBL_TUMGIRISLER SET LIFOKALANMIKTAR = 0, LIFOKALANTUTAR = 0 WHERE CURRENT OF CUR;
            
            KALANMIKTAR = KALANMIKTAR - LGMIKTAR;   
                
            IF (KALANMIKTAR = 0) THEN LEAVE;
         END
         
         FETCH PRIOR FROM CUR INTO GID, GFIYAT, LGMIKTAR, LGTUTAR;
      END
      
      CLOSE CUR;
   END
   
   MERGE INTO TBL_TUMKAYITLAR T USING (SELECT ID, SUM(CMALIYET) CMALIYET FROM TBL_LIFODETAY GROUP BY ID) L ON L.ID = T.ID
      WHEN MATCHED THEN UPDATE SET T.LIFO_MALIYET = L.CMALIYET;
END
^

CREATE PROCEDURE RPT_DETAYLI_FIFO_LIFO (DECIMAL_SEPERATOR CHAR(1) = ',' )
RETURNS (
    STOK_ID INTEGER,
    STOK_ADI VARCHAR(100),
    GC SMALLINT,
    TARIH DATE,
    EVRAK_NO VARCHAR(30),
    ACIKLAMA VARCHAR(500),
    MIKTAR DECIMAL(18,4),
    FIYAT DECIMAL(18,6),
    TUTAR DECIMAL(18,2),
    ORT_AGIRLIKLI_MALIYET DECIMAL(18,2),
    ORT_HAREKETLI_MALIYET DECIMAL(18,2),
    FIFO_MALIYET DECIMAL(18,2),
    LIFO_MALIYET DECIMAL(18,2),
    KALAN_MIKTAR DECIMAL(18,4),
    ORT_AGIRLIKLI_KALAN_TUTAR DECIMAL(18,2),
    ORT_HAREKETLI_KALAN_TUTAR DECIMAL(18,2),
    FIFO_KALAN_TUTAR DECIMAL(18,2),
    LIFO_KALAN_TUTAR DECIMAL(18,2))
AS
DECLARE ID BIGINT;
DECLARE FUNCTION DATEFORMAT(D DATE) RETURNS VARCHAR(8)
AS
DECLARE YYYY SMALLINT;
BEGIN
   YYYY = EXTRACT(YEAR FROM D) - 2000;
   /*IF (YYYY - 1999 > 0) THEN YYYY = YYYY - 2000; ELSE YYYY = YYYY - 1900;*/
   RETURN EXTRACT(DAY FROM D) || '.' || EXTRACT(MONTH FROM D) || '.' || YYYY;
END
BEGIN
   FOR SELECT ID, STOKID, STOKADI, GC, TARIH, EVRAKNO, ACIKLAMA, MIKTAR, FIYAT, TUTAR, ORT_AGIRLIKLI_MALIYET, ORT_HAREKETLI_MALIYET, FIFO_MALIYET, LIFO_MALIYET,
              SUM(DECODE(GC, 1, MIKTAR, -MIKTAR)) OVER (PARTITION BY STOKID ORDER BY ID) KALAN_MIKTAR,       
              ORT_AGIRLIKLI_KALAN_TUTAR, ORT_HAREKETLI_KALAN_TUTAR,
              SUM(DECODE(GC, 1, TUTAR, -FIFO_MALIYET)) OVER (PARTITION BY STOKID ORDER BY ID) FIFO_KALAN_TUTAR,
              SUM(DECODE(GC, 1, TUTAR, -LIFO_MALIYET)) OVER (PARTITION BY STOKID ORDER BY ID) LIFO_KALAN_TUTAR
       FROM TBL_TUMKAYITLAR tk
       INTO ID, STOK_ID,STOK_ADI,GC,TARIH, EVRAK_NO,ACIKLAMA,MIKTAR,FIYAT,TUTAR,ORT_AGIRLIKLI_MALIYET,ORT_HAREKETLI_MALIYET,FIFO_MALIYET,LIFO_MALIYET,KALAN_MIKTAR,
            ORT_AGIRLIKLI_KALAN_TUTAR,ORT_HAREKETLI_KALAN_TUTAR,FIFO_KALAN_TUTAR,LIFO_KALAN_TUTAR DO
   BEGIN
      SUSPEND;
      
      IF (GC = 2) THEN
      BEGIN
         SELECT LIST(DATEFORMAT(tk.TARIH) || ' -> ' || tk.EVRAKNO || ' -> ' || DECODE(:DECIMAL_SEPERATOR, ',', REPLACE(fd.CMIKTAR, '.', ','), fd.CMIKTAR) , ASCII_CHAR(13) || ASCII_CHAR(10))
         FROM TBL_FIFODETAY fd
            INNER JOIN TBL_TUMKAYITLAR tk ON fd.IDGIRIS = tk.ID WHERE fd.ID = :ID INTO ACIKLAMA;
         
         EVRAK_NO = 'FIFO DETAY'; STOK_ID = NULL; STOK_ADI = NULL; GC = NULL; TARIH = NULL; MIKTAR = NULL; FIYAT = NULL; TUTAR = NULL; ORT_AGIRLIKLI_MALIYET = NULL;
         ORT_HAREKETLI_MALIYET = NULL; FIFO_MALIYET = NULL; LIFO_MALIYET = NULL; KALAN_MIKTAR = NULL; ORT_AGIRLIKLI_KALAN_TUTAR = NULL; ORT_HAREKETLI_KALAN_TUTAR = NULL;
         FIFO_KALAN_TUTAR = NULL; LIFO_KALAN_TUTAR = NULL;
         
         IF (ACIKLAMA IS NOT NULL) THEN SUSPEND;
         
         EVRAK_NO = 'LIFO DETAY';
         SELECT LIST(DATEFORMAT(tk.TARIH) || ' -> ' || tk.EVRAKNO || ' -> ' || DECODE(:DECIMAL_SEPERATOR, ',', REPLACE(ld.CMIKTAR, '.', ','), ld.CMIKTAR), ASCII_CHAR(13) || ASCII_CHAR(10))
         FROM TBL_LIFODETAY ld
            INNER JOIN TBL_TUMKAYITLAR tk ON ld.IDGIRIS = tk.ID WHERE ld.ID = :ID INTO ACIKLAMA;
                 
         IF (ACIKLAMA IS NOT NULL) THEN SUSPEND;         
      END      
   END
END
^

CREATE PROCEDURE CMD_MALIYET_CALISTIR (AGIRLIKLI_AYLIK SMALLINT = 0)
AS
DECLARE IDX_NAME  VARCHAR(31);
DECLARE vSTOKID   INTEGER;
DECLARE vSTOKADI  VARCHAR(80);
DECLARE vGC       SMALLINT;
DECLARE vTARIH    DATE;
DECLARE vAY_INDEX INTEGER;
DECLARE vEVRAKNO  VARCHAR(30);
DECLARE vACIKLAMA VARCHAR(80);
DECLARE vMIKTAR   DECIMAL(18,4);
DECLARE vFIYAT    DECIMAL(18,6);
DECLARE vTUTAR    DECIMAL(18,2);
BEGIN
   FOR SELECT RDB$INDEX_NAME FROM RDB$INDICES WHERE RDB$SYSTEM_FLAG = 0 INTO IDX_NAME DO
   BEGIN
      EXECUTE STATEMENT 'ALTER INDEX ' || IDX_NAME || ' INACTIVE';
   END
   
   -- Test icin gerekli temizlik...
   -- DELETE FROM TBL_FIFODETAY;
   -- DELETE FROM TBL_LIFODETAY;
   -- DELETE FROM TBL_AGIRLIKLI_PARENTDETAY;
   -- DELETE FROM TBL_TUMGIRISLER;
   -- DELETE FROM TBL_TUMKAYITLAR;
   -- Test temizligi sonu...   
 
   -- EXECUTE STATEMENT 'ALTER TABLE TBL_TUMKAYITLAR ALTER COLUMN ID RESTART';   
/*   
   FOR EXECUTE STATEMENT 'SELECT STOKID, TRIM(STOKADI), GC, TARIH, EXTRACT(YEAR FROM CAST(TARIH AS DATE)) || LPAD(EXTRACT(MONTH FROM CAST(TARIH AS DATE)), 2, 0),
                          TRIM(EVRAKNO), TRIM(ACIKLAMA), MIKTAR, FIYAT, TUTAR FROM TMP'
               INTO vSTOKID, vSTOKADI, vGC, vTARIH, vAY_INDEX, vEVRAKNO, vACIKLAMA, vMIKTAR, vFIYAT, vTUTAR DO
   BEGIN
      INSERT INTO TBL_TUMKAYITLAR (STOKID, STOKADI, GC, TARIH, AY_INDEX, EVRAKNO, ACIKLAMA, MIKTAR, FIYAT, TUTAR)
         VALUES(:vSTOKID, :vSTOKADI, :vGC, :vTARIH, :vAY_INDEX, :vEVRAKNO, :vACIKLAMA, :vMIKTAR, :vFIYAT, :vTUTAR);
   END
*/

   EXECUTE STATEMENT 'INSERT INTO TBL_TUMKAYITLAR (STOKID, STOKADI, GC, TARIH, AY_INDEX, EVRAKNO, ACIKLAMA, MIKTAR, FIYAT, TUTAR)
                       SELECT STOKID, TRIM(STOKADI), GC, TARIH, EXTRACT(YEAR FROM TARIH) || LPAD(EXTRACT(MONTH FROM TARIH), 2, 0),
                          TRIM(EVRAKNO), TRIM(ACIKLAMA), MIKTAR, FIYAT, TUTAR FROM TMP';
   
   EXECUTE STATEMENT 'ALTER INDEX IDX_TUMKAYITLAR_ID_DES ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_TUMKAYITLAR_ID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_TUMKAYITLAR_STKID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_TUMKAYITLAR_AYINDEX_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_TUMKAYITLAR_GC_ASC ACTIVE';   
   EXECUTE STATEMENT 'ALTER INDEX IDX_GIRISLER_ID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_GIRISLER_STOKID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_GIRISLER_TARIH_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_GIRISLER_KALANFIFO_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_GIRISLER_KALANLIFO_ASC ACTIVE';   
   EXECUTE STATEMENT 'ALTER INDEX IDX_FIFODETAY_ID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_FIFODETAY_IDGIRIS_ASC ACTIVE';   
   EXECUTE STATEMENT 'ALTER INDEX IDX_LIFODETAY_ID_ASC ACTIVE';
   EXECUTE STATEMENT 'ALTER INDEX IDX_LIFODETAY_IDGIRIS_ASC ACTIVE';
   
   INSERT INTO TBL_TUMGIRISLER SELECT ID, STOKID, TARIH, FIYAT, MIKTAR, TUTAR, MIKTAR, TUTAR FROM TBL_TUMKAYITLAR WHERE GC = 1;
      
   IF (AGIRLIKLI_AYLIK = 0) THEN EXECUTE PROCEDURE INTERNAL_AGIRLIKLI_ORTALAMA_GENEL; ELSE EXECUTE PROCEDURE INTERNAL_AGIRLIKLI_ORTALAMA_AYLIK;
      
   EXECUTE PROCEDURE INTERNAL_HAREKETLI_ORTALAMA;
   EXECUTE PROCEDURE INTERNAL_FIFO;
   EXECUTE PROCEDURE INTERNAL_LIFO;
END
^

SET TERM ;^

CREATE INDEX IDX_FIFODETAY_IDGIRIS_ASC ON TBL_FIFODETAY (IDGIRIS);
CREATE INDEX IDX_FIFODETAY_ID_ASC ON TBL_FIFODETAY (ID);
CREATE INDEX IDX_LIFODETAY_IDGIRIS_ASC ON TBL_LIFODETAY (IDGIRIS);
CREATE INDEX IDX_LIFODETAY_ID_ASC ON TBL_LIFODETAY (ID);
CREATE UNIQUE INDEX IDX_GIRISLER_ID_ASC ON TBL_TUMGIRISLER (ID);
CREATE INDEX IDX_GIRISLER_KALANFIFO_ASC ON TBL_TUMGIRISLER (FIFOKALANMIKTAR);
CREATE INDEX IDX_GIRISLER_KALANLIFO_ASC ON TBL_TUMGIRISLER (LIFOKALANMIKTAR);
CREATE INDEX IDX_GIRISLER_STOKID_ASC ON TBL_TUMGIRISLER (STOKID);
CREATE INDEX IDX_GIRISLER_TARIH_ASC ON TBL_TUMGIRISLER (TARIH);
CREATE INDEX IDX_TUMKAYITLAR_AYINDEX_ASC ON TBL_TUMKAYITLAR (AY_INDEX);
CREATE INDEX IDX_TUMKAYITLAR_GC_ASC ON TBL_TUMKAYITLAR (GC);
CREATE UNIQUE INDEX IDX_TUMKAYITLAR_ID_ASC ON TBL_TUMKAYITLAR (ID);
CREATE UNIQUE DESCENDING INDEX IDX_TUMKAYITLAR_ID_DES ON TBL_TUMKAYITLAR (ID);
CREATE INDEX IDX_TUMKAYITLAR_STKID_ASC ON TBL_TUMKAYITLAR (STOKID);

 

 Hayır duanızı eksik etmeden programı aşağıdaki bağlantıdan indirebilirsiniz.

 Esenlikler dilerim...

 

İndir : Stok_Degerleme (22,9 MB)

Yorumlar

  1. Merhaba Zeki Bey,

    Bu tarz işlerle uğraşan kişiler için eşsiz bir kaynak olmuş.

    Elinize emeğinize sağlık. Paylaşımınız için çok teşekkürler.

    YanıtlaSil
  2. Emeğine sağlık

    YanıtlaSil

Yorum Gönder

Bu blogdaki popüler yayınlar

Firefox Webrowser For VBA

VBA: Common controls Enter/Exit events and fast WinAPI call with Type Library