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ı
Editör ekibi
10 dk okuma
İçindekiler
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 = 1değerini satış sanmak. Doğrusu: 1 alış, 2 satış.ACTIVE = 0yerineACTIVE = 1filtrelemek; Logo'da 0 aktif kart demektir.INCVATkolonunu yok sayıp KDV dahil fiyatı KDV hariç gibi raporlamak.- Güncel fiyatı
MAX(PRICE)ile bulmaya çalışmak; doğrusuORDER BY BEGDATE DESCileTOP 1. PRCLISTileITEMStablosunuINNER JOINile birleştirip fiyatı tanımsız ürünleri raporun dışında bırakmak.- Ürün bağını
CARDREFyerine stok kodu üzerinden kurmak; kod değişince rapor bozulur. - Farklı
CURRENCYdeğerlerindeki kartları tek kolonda toplayıp ortaya anlamsız bir ortalama çıkarmak. - Firma önekini unutup "Invalid object name" hatası almak:
LG_{firma}_PRCLIST. - Sorguda
@stokgibi bir değişkeni kullanıpDECLAREsatı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 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.




