ERP Asistanı Dal Net
Logo SQL

Logo Fiyat Listesi SQL: PRCLIST ile Satış ve Alış Fiyatları

Logo PRCLIST tablosundan satış ve alış fiyatlarını çeken hazır SQL sorguları: PTYPE, INCVAT, CURRENCY tuzakları ve fiyatı tanımsız ürün listesi.

Erp Asistanı Erp Asistanı Editör ekibi 10 dk okuma
Logo Fiyat Listesi SQL: PRCLIST ile Satış ve Alış Fiyatları

Logo'da satış fiyatını SQL ile çekmek isteyenlerin çoğu ilk denemede yanlış sonuç alır: ya alış fiyatını satış sanır, ya KDV dahil fiyatı KDV hariç sanır, ya da pasif fiyat kartlarını listeye katar. Hatanın ortak sebebi şu: fiyatlar malzeme kartında değil, ayrı bir tabloda, PRCLIST içinde tutulur ve bu tablonun üç kolonu (PTYPE, ACTIVE, INCVAT) yanlış okunduğunda rapor sessizce yanlışa döner. Hata mesajı almazsınız, sadece yanlış fiyat görürsünüz. Bu yazıda güncel fiyatı seçme kalıbını ve doğrudan çalışan yedi sorguyu bulacaksınız. Tablo mantığına yeni ısınıyorsanız önce Logo tablo yapısı rehberine göz atmanızı öneririm.

Önce önek kuralı: PRCLIST bir firma-master tablodur

Logo'da tablo adları gerçek veritabanında firma ve dönem öneki taşır. PRCLIST ve ITEMS dönemsiz kart tabloları olduğu için önekleri LG_{firma}_ biçimindedir: LG_323_PRCLIST, LG_323_ITEMS. Aşağıdaki sorgularda tabloları mantıksal adıyla yazdım; kendi veritabanınızda çalıştırırken başına kendi firma numaranızı eklemeniz gerekir. Fiyat kartı firma-master olduğu için burada dönem numarası kullanılmaz.

PRCLIST kolonları: hangi alan ne işe yarar

Kolon Anlamı Dikkat
CARDREF Malzeme bağı (ITEMS.LOGICALREF) Kod değil, sayısal ref
PTYPE 1 = alış, 2 = satış Tersini varsaymak en yaygın hata
ACTIVE 0 = aktif kart, 1 = pasif Logo ters konvansiyon kullanır
PRICE Liste fiyatı INCVAT değerine göre KDV dahil ya da hariç
INCVAT 1 = fiyat KDV dahil 0 ise fiyat KDV hariçtir
CURRENCY Döviz kodu Farklı dövizdeki kartları toplamayın
BEGDATE / ENDDATE Geçerlilik penceresi Güncel fiyat = en yeni BEGDATE
PRIORITY Öncelik Aynı pencerede tercih sırası
UOMREF Birim bağı Birim çevrimi gerekebilir
CODE Fiyat kartı kodu PTYPE + ACTIVE + CODE benzersizdir
CLIENTCODE / CLSPECODE Cari bazlı fiyat Cari-özel kartlar burada ayrışır
PAYPLANREF Ödeme planı bağı Vade bazlı fiyatlandırma

Tablo, malzeme kartıyla CARDREF = ITEMS.LOGICALREF üzerinden bağlanır. CODE ile bağ kurmaya çalışmak, stok kodu değiştiğinde sessizce boş sonuç üretir.

PTYPE: 1 alış, 2 satış - tersini varsaymayın

Bu, fiyat listesi raporlarındaki bir numaralı hata kaynağıdır. Satış fiyatı için PTYPE = 2, alış fiyatı için PTYPE = 1 filtreleyin. Tersi yapıldığında rapor hata vermez; satış ekranında alış fiyatını görürsünüz. Kurulumların çoğunda alış fiyatı az sayıda ürün için tanımlı olduğundan, hata çoğu satırda "fiyat boş" olarak da kendini belli eder.

Kendi veritabanınızda dağılımı bir kez görmek için şu teşhis sorgusunu çalıştırın:

SELECT P.PTYPE,
       CASE P.PTYPE WHEN 1 THEN N'Alış' WHEN 2 THEN N'Satış' ELSE N'Diğer' END AS fiyat_tipi,
       COUNT(*) AS kart_adedi,
       COUNT(DISTINCT P.CARDREF) AS urun_adedi
FROM PRCLIST P
WHERE P.ACTIVE = 0
GROUP BY P.PTYPE;

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

Satış kartlarının sayısı belirgin şekilde fazla çıkıyorsa yön doğru demektir. ACTIVE = 0 filtresini ihmal ederseniz pasif kartlar da sayıya karışır.

Güncel fiyat nasıl seçilir

Aynı ürüne birden çok fiyat kartı tanımlanabilir; bu bir hata değil, tarih pencereli fiyatlandırmanın doğal sonucudur. Güncel fiyat MAX(PRICE) ile bulunmaz, en yeni başlangıç tarihli kart seçilir: ORDER BY BEGDATE DESC ile TOP 1. MAX(PRICE) kullanmak size listenin en pahalı fiyatını döndürür, güncel fiyatı değil. Aynı BEGDATE değerine sahip iki kart varsa PRIORITY ve sonrasında LOGICALREF sıralamasıyla kararı netleştirin.

1. Tek ürünün güncel satış ve alış fiyatı

Aşağıdaki sorgular tek başına çalışsın diye üstte @stok değişkeni tanımlıdır; kendi ürününüz için değerini stok koduyla değiştirin.

DECLARE @stok VARCHAR(50) = (SELECT TOP 1 CODE FROM ITEMS WHERE ACTIVE = 0 ORDER BY CODE);

SELECT I.CODE, I.NAME,
       S.PRICE    AS satis_fiyat,
       S.INCVAT   AS satis_kdv_dahil,
       S.CURRENCY AS satis_doviz,
       A.PRICE    AS alis_fiyat,
       A.CURRENCY AS alis_doviz
FROM ITEMS I
OUTER APPLY (
    SELECT TOP 1 P.PRICE, P.INCVAT, P.CURRENCY
    FROM PRCLIST P
    WHERE P.CARDREF = I.LOGICALREF
      AND P.PTYPE = 2
      AND P.ACTIVE = 0
    ORDER BY P.BEGDATE DESC, P.LOGICALREF DESC
) S
OUTER APPLY (
    SELECT TOP 1 P.PRICE, P.INCVAT, P.CURRENCY
    FROM PRCLIST P
    WHERE P.CARDREF = I.LOGICALREF
      AND P.PTYPE = 1
      AND P.ACTIVE = 0
    ORDER BY P.BEGDATE DESC, P.LOGICALREF DESC
) A
WHERE I.ACTIVE = 0
  AND I.CODE = @stok;

OUTER APPLY kullanmamın sebebi: alış fiyatı tanımlı olmayan üründe satır kaybolmasın, alış tarafı boş gelsin. INNER JOIN yazarsanız satış fiyatı olan ama alış fiyatı olmayan ürünler listeden tamamen düşer.

2. Satış fiyatlarını KDV dahil/hariç normalize etme

INCVAT = 1 ise PRICE KDV dahildir; raporunuzda tek tip fiyat görmek istiyorsanız stok kartındaki oranla (ITEMS.VAT) çevirin:

SELECT I.CODE, I.NAME, I.VAT,
       P.PRICE AS liste_fiyat,
       P.INCVAT,
       CASE WHEN P.INCVAT = 1
            THEN ROUND(P.PRICE / (1 + ISNULL(I.VAT, 0) / 100.0), 2)
            ELSE P.PRICE END AS kdv_haric_fiyat,
       CASE WHEN P.INCVAT = 0
            THEN ROUND(P.PRICE * (1 + ISNULL(I.VAT, 0) / 100.0), 2)
            ELSE P.PRICE END AS kdv_dahil_fiyat
FROM PRCLIST P
JOIN ITEMS I ON I.LOGICALREF = P.CARDREF
WHERE P.ACTIVE = 0
  AND P.PTYPE = 2
  AND I.ACTIVE = 0
ORDER BY I.CODE;

Sabit bir KDV oranı (1.20 gibi) yazmayın; oran stok kartından gelmeli. VAT oran olarak tutulur, çarpan olarak değil.

3. Ürün başına tüm fiyat kartları

SELECT I.CODE, I.NAME,
       P.CODE AS fiyat_kodu,
       CASE P.PTYPE WHEN 1 THEN N'Alış' WHEN 2 THEN N'Satış' ELSE N'Diğer' END AS fiyat_tipi,
       P.PRICE, P.CURRENCY, P.INCVAT, P.BEGDATE, P.ENDDATE, P.PRIORITY
FROM PRCLIST P
JOIN ITEMS I ON I.LOGICALREF = P.CARDREF
WHERE P.ACTIVE = 0
  AND I.ACTIVE = 0
ORDER BY I.CODE, P.PTYPE, P.BEGDATE DESC;

Bu çıktı, aynı ürüne neden iki farklı fiyat gördüğünüzü açıklar: tarih pencereleri farklı kartlar. Cari bazlı fiyat kurgusunun mantığını bayiye özel fiyat ve iskonto yönetimi yazısında ayrıca anlattım.

4. Satış fiyatı tanımsız aktif ürünler

SELECT I.CODE, I.NAME, I.VAT
FROM ITEMS I
WHERE I.ACTIVE = 0
  AND NOT EXISTS (
      SELECT 1
      FROM PRCLIST P
      WHERE P.CARDREF = I.LOGICALREF
        AND P.PTYPE = 2
        AND P.ACTIVE = 0
  )
ORDER BY I.CODE;

Bu liste, sipariş ekranında fiyatı boş görünen ürünlerin tam listesidir. Yalnızca ticari malları görmek istiyorsanız AND I.CARDTYPE = 1 ekleyin; hizmet kartları da fiyat listesinde yer aldığı için sonuç kalabalıklaşabilir.

5. Alış-satış marjı

WITH fiyat AS (
    SELECT P.CARDREF, P.PTYPE, P.PRICE,
           ROW_NUMBER() OVER (PARTITION BY P.CARDREF, P.PTYPE
                              ORDER BY P.BEGDATE DESC, P.LOGICALREF DESC) AS sira
    FROM PRCLIST P
    WHERE P.ACTIVE = 0
      AND P.PTYPE IN (1, 2)
),
guncel AS (
    SELECT I.CODE, I.NAME,
           MAX(CASE WHEN F.PTYPE = 2 THEN F.PRICE END) AS satis_fiyat,
           MAX(CASE WHEN F.PTYPE = 1 THEN F.PRICE END) AS alis_fiyat
    FROM fiyat F
    JOIN ITEMS I ON I.LOGICALREF = F.CARDREF
    WHERE F.sira = 1
      AND I.ACTIVE = 0
    GROUP BY I.CODE, I.NAME
)
SELECT CODE, NAME, satis_fiyat, alis_fiyat,
       CASE WHEN ISNULL(alis_fiyat, 0) > 0
            THEN ROUND((satis_fiyat - alis_fiyat) / alis_fiyat * 100, 2)
            END AS marj_yuzde
FROM guncel
WHERE satis_fiyat IS NOT NULL
  AND alis_fiyat IS NOT NULL
ORDER BY marj_yuzde ASC;

Liste başında negatif ya da çok düşük marjlı ürünler çıkar; bunlar ya eski alış fiyatıyla satılan ya da satış fiyatı güncellenmemiş kalemlerdir. Fiyat sapmasını satın alma tarafında yakalama yöntemini alış fiyat sapması nasıl yakalanır yazısında bulabilirsiniz.

6. Tek ürünün fiyat geçmişi

DECLARE @stok VARCHAR(50) = (SELECT TOP 1 CODE FROM ITEMS WHERE ACTIVE = 0 ORDER BY CODE);

SELECT P.CODE AS fiyat_kodu,
       CASE P.PTYPE WHEN 1 THEN N'Alış' WHEN 2 THEN N'Satış' ELSE N'Diğer' END AS fiyat_tipi,
       P.PRICE, P.CURRENCY, P.INCVAT, P.BEGDATE, P.ENDDATE, P.PRIORITY
FROM PRCLIST P
WHERE P.CARDREF = (SELECT LOGICALREF FROM ITEMS WHERE CODE = @stok)
  AND P.ACTIVE = 0
ORDER BY P.PTYPE, P.BEGDATE DESC;

Bu sorgu "bu ürünün fiyatı ne zaman değişti" sorusunun cevabıdır. Geçmişi görmek için ACTIVE = 0 filtresini kaldırıp pasif kartları da listeleyebilirsiniz; ama güncel fiyat raporunda bu filtre mutlaka kalmalı. Dövizli kartlar varsa CURRENCY kolonunu da çıktıya alın, TL ile döviz fiyatını aynı kolonda toplamayın.

Sık yapılan hatalar

  • PTYPE = 1 değerini satış sanmak. Doğrusu: 1 alış, 2 satış.
  • ACTIVE = 0 yerine ACTIVE = 1 filtrelemek; Logo'da 0 aktif kart demektir.
  • INCVAT kolonunu yok sayıp KDV dahil fiyatı KDV hariç gibi raporlamak.
  • Güncel fiyatı MAX(PRICE) ile bulmaya çalışmak; doğrusu ORDER BY BEGDATE DESC ile TOP 1.
  • PRCLIST ile ITEMS tablosunu INNER JOIN ile birleştirip fiyatı tanımsız ürünleri raporun dışında bırakmak.
  • Ürün bağını CARDREF yerine stok kodu üzerinden kurmak; kod değişince rapor bozulur.
  • Farklı CURRENCY değerlerindeki kartları tek kolonda toplayıp ortaya anlamsız bir ortalama çıkarmak.
  • Firma önekini unutup "Invalid object name" hatası almak: LG_{firma}_PRCLIST.
  • Sorguda @stok gibi bir değişkeni kullanıp DECLARE satırını atlamak; betik "Must declare the scalar variable" hatası verir.

Sık sorulanlar

PRCLIST'te PTYPE 2 satış fiyatı mı? Evet. 2 satış, 1 alış. Tersini varsaymak en yaygın hata olduğu için raporu bir kez teşhis sorgusuyla doğrulayın.

Fiyat KDV dahil mi, hariç mi? Kart bazında değişir. INCVAT = 1 ise PRICE KDV dahildir; 0 ise KDV hariçtir. Aynı raporda iki tip kart bulunabilir, bu yüzden normalize etmeden toplam almayın.

Aynı ürüne iki satış fiyatı tanımlıysa hangisi gelir? Geçerlilik penceresine uyan en yeni BEGDATE değerine sahip kart gelir. Eşitlik varsa PRIORITY, sonra LOGICALREF sırası belirleyicidir.

Fiyatı olan ürün neden listede yok? Muhtemelen PTYPE yanlış ya da fiyat kartı pasif. Fiyatlar malzeme kartında değil PRCLIST içinde tutulur; ACTIVE = 0 ve PTYPE = 2 filtrelerini birlikte kontrol edin.


Bu sorguları elle yazmak yerine Erp Asistanı ile Türkçe sorabilirsiniz: "satış fiyatı tanımsız aktif ürünleri getir" dersiniz, sistem Logo şemasına uygun (LG önekleri, LOGICALREF bağları, PTYPE ve INCVAT doğru) çalışan SQL'i üretir. Hazır kalıplara göz atmak için Logo hazır SQL sorguları yazısına bakabilirsiniz. Hemen kaydolun ve ilk fiyat listenizi sorgulayın →

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.