Finans uzmanı yazıyor: “Raporunuz toplam satışı 1.250.772,45 ₺ diyor, bizim ERP dökümü 1.346.189,85 ₺. Hangisi doğru?” İkisi de doğru olabilir. Fark tam olarak 95.417,40 ₺ ve bu, iptal edilen satırların tutarıdır: ERP tüm satırları topluyor, rapordaki [Net Satış] iptalleri dışlıyor. Bu cevabı beş dakikada verebilmek için mutabakatı önceden yapmış olman gerekir. Kullanıcı bir kez “bu rapor yanlış” derse, sonra doğru da olsa güveni geri kazanmak zordur.
Veri mutabakatı: rapor kaynağı tutuyor mu?
Mutabakat (reconciliation), rapordaki sayıların kaynak sistemdeki sayılarla aynı kurala göre aynı sonucu verdiğini göstermektir. Üç katmanda yapılır:
- Satır sayısı: Kaynakta kaç satır var, modelde kaç satır var? Bizim modelde Satislar tablosu 1.620 satır;
SatirNosütununda da 1.620 farklı değer var, yani yinelenen satır yok. - Kontrol toplamları (control totals): Ham tutar toplamı, durumlara göre dağılım. Ham tutar 1.346.189,85 ₺; iptal 95.417,40 ₺; ikisinin farkı net satış 1.250.772,45 ₺.
- Dönem kırılımı: Toplam tutsa bile aylar kayabilir (saat dilimi, yanlış tarih sütunu). Yıl ve ay düzeyinde karşılaştır.
| Yıl | Satır | Ham tutar | Net satış |
|---|---|---|---|
| 2022 | 105 | 109.278,30 ₺ | 102.837,20 ₺ |
| 2023 | 550 | 428.549,90 ₺ | 400.869,55 ₺ |
| 2024 | 965 | 808.361,65 ₺ | 747.065,70 ₺ |
| Toplam | 1.620 | 1.346.189,85 ₺ | 1.250.772,45 ₺ |
Kaynak taraftaki karşılığını SQL ile alırsın (COUNT(*), SUM(Tutar), yıla göre GROUP BY); bunun için “Power BI analisti için SQL” dersine bak. Model tarafında aynı tabloyu DAX sorgu görünümünde (DAX query view) tek sorguyla üretirsin:
EVALUATE
ROW(
"Satır", COUNTROWS(Satislar),
"Tekil satır", DISTINCTCOUNT(Satislar[SatirNo]),
"Ham tutar", SUM(Satislar[Tutar]),
"İptal", CALCULATE(SUM(Satislar[Tutar]), Satislar[Durum] = "İptal"),
"Net", [Net Satış]
)
Test sayfası ve DAX sorgu test paketi
Yazılımcılar kodlarını otomatik testlerle korur; ölçülerini sen de koruyabilirsin. Fikir: bilinen değerleri (brifteki ya da mutabakattaki sayılar) bir tabloya yaz, ölçülerin bugünkü sonucunu yanına koy ve farkı işaretle. Bir ölçüyü değiştirdikten sonra sorguyu tekrar çalıştırırsın; “FARK” görürsen bir şeyi bozmuşsundur.
EVALUATE
VAR Testler =
DATATABLE(
"Test", STRING, "Beklenen", DOUBLE,
{
{ "Satır sayısı", 1620 },
{ "Net satış", 1250772.45 },
{ "Sipariş sayısı", 838 }
}
)
VAR Sonuc =
ADDCOLUMNS(
Testler,
"Gerçek",
SWITCH(
[Test],
"Satır sayısı", COUNTROWS(Satislar),
"Net satış", [Net Satış],
"Sipariş sayısı", [Sipariş Sayısı]
)
)
RETURN
ADDCOLUMNS(Sonuc, "Durum", IF(ABS([Gerçek] - [Beklenen]) < 0.01, "OK", "FARK"))
= karşılaştırması “FARK” der. Para tutarlarını her zaman bir tolerans ile karşılaştır: ABS(Gerçek - Beklenen) < 0.01.Aynı testleri raporda gizli bir Test sayfasına da koyabilirsin: her test için bir kart, kart değeri “OK” ya da “FARK” döndüren bir ölçü. Sayfa yayımlanan uygulamada gizlenir; geliştirici her yayından önce bakar.
Uç durumlar: testin asıl yeri
Ölçülerin çoğu ortalama durumda doğru çalışır. Hatalar kenarlarda saklanır. Bizim modelde her biri gerçek olan beş kenar:
| Uç durum | Bu modelde | Ne kontrol edersin? |
|---|---|---|
| Boş değer | 131 satırda KargoGun boş: 121’i iptal, 10’u aralık 2024’te hâlâ kargoda olan sipariş. | Boşluk beklenen bir durum mu (henüz teslim edilmedi) yoksa veri hatası mı? Ortalama kargo günü boşları atlar; bunu tanıma yaz. |
| Eksik boyut bilgisi | 7 müşterinin şehri boş; bu müşterilerin net satışı 63.852,75 ₺. | Şehir grafiğinde “(Boş)” çubuğu çıkar. Gizlemek yerine veri sahibine bildir. |
| Kısmi dönem | Satışlar 22 Haziran 2022’de başlıyor; haziran 2022 net satışı yalnızca 595 ₺. Temmuz 2022’nin aylık büyümesi bu yüzden +%1.902,7 görünür. Hedefler ise ocak 2022’den başlıyor: ilk beş ayın 17.500 ₺ hedefi satışsız kaldığı için 2022 gerçekleşmesi %77,0. | Büyüme ve hedef ölçülerini ilk ve son dönemde dene. Gerekirse kısmi dönemi rapordan dışla ya da not düş. |
| Sıfıra bölme | Önceki ayı olmayan ilk ayda [MoM %] boş döner, çünkü DIVIDE kullanılıyor. | Her oranda / yerine DIVIDE; “BLANK, hatalar ve DAX’ta hata ayıklama” dersine bak. |
| Toplam satırı | Kategori satırlarındaki sipariş sayılarının toplamı 1.377, toplam satırı 838. Kategorilerin ortalama sepetlerini toplasan 6.251,44 ₺ eder; gerçek ortalama sepet 1.492,57 ₺. | Toplam satırı satırların toplamı olmak zorunda değildir: bir sipariş birden çok kategoride ürün içerebilir, ortalamalar toplanmaz. Kullanıcıya bunun hata olmadığını açıklayan bir not ekle. |
Bunlara ek olarak her sayfayı filtrelerle dene: tek bir yıl, hiç verisi olmayan bir kategori ve kanal kombinasyonu, birden çok dilimleyici seçimi. Satır düzeyi güvenlik varsa “Rol olarak görüntüle” ile her rolü tek tek test et (“Satır ve nesne düzeyinde güvenlik” dersi).
Veri sözlüğü: her ölçünün kimliği
Veri sözlüğü (data dictionary), modeldeki her ölçünün ve önemli sütunun ne anlama geldiğini yazan tablodur. Raporu devralan kişinin ilk açtığı belgedir.
| Ölçü | İş tanımı | Biçim | Sahip | Bilinen değer |
|---|---|---|---|---|
| Net Satış | İptal olmayan satırların indirim sonrası tutarı. İadeler dahil. | #.##0,00 ₺ | Finans | Tüm yıllar 1.250.772,45 ₺ |
| Sipariş Sayısı | İptal olmayan farklı sipariş numarası sayısı. Kategoriler toplanmaz. | #.##0 | Satış | 838 |
| MoM % | Net satışın önceki aya göre değişimi. İlk ayda boş. | %0,0 | Satış | Aralık 2024: %5,6 |
Tanımı modelin içine de yaz: Model görünümünde ölçüyü seçip Özellikler bölmesindeki Açıklama (Description) alanını doldurursan, kullanıcı Veri bölmesinde ölçünün üzerine geldiğinde bu metni görür. Sözlüğün ham hâlini DAX sorgu görünümünde INFO.VIEW.MEASURES() fonksiyonu verir: her ölçünün adı, tablosu, açıklaması, ifadesi ve biçim dizesi gelir. İfade sütununu yalnızca modelde yazma izni olanlar görür.
EVALUATE
SELECTCOLUMNS(
INFO.VIEW.MEASURES(),
"Ölçü", [Name],
"Açıklama", [Description],
"Biçim", [FormatString],
"İfade", [Expression]
)
Sürüm notları
Her yayında kısa bir not yaz ve raporun “Hakkında” sayfasına ya da çalışma alanındaki bir belgeye ekle:
Sürüm notunun en önemli satırı etkisidir: kullanıcı, dün indirdiği Excel’deki sayının neden bugün farklı olduğunu orada görür. Dosyaları PBIP biçiminde Git’te tutuyorsan, not commit mesajıyla birlikte geçmişe de yazılır (“Yaşam döngüsü: PBIP, TMDL, Git, dağıtım işlem hatları, şablonlar” dersi).
Kullanıcı kabul testi (UAT)
Kullanıcı kabul testi (user acceptance testing), raporu yapan değil kullanan kişinin, brifteki kabul kriterlerine göre “evet, bu iş görüyor” demesidir. Kriterleri brifte yazmıştın; burada testi yönetiyorsun:
- Test kişilerini seç: her rolden en az bir kullanıcı (müdür, bölge sorumlusu).
- Senaryo ver, tur verme: “Aralıkta hedefin altında kalan kategoriyi bul ve geçen yılla karşılaştır.” Kullanıcı kendisi yapsın.
- Bulguları tek listede topla: madde, kim buldu, önem (engelleyici / önemli / küçük), durum.
- Engelleyici yoksa onay al: e-postayla ya da iş takip aracında “Kabul edildi” durumu, tarih ve kişi.
Yayımlamadan önce kontrol listesi
- Test sorgusu ve test sayfası: tüm satırlar OK.
- Mutabakat tablosu güncel; son kontrolden sonra kaynakta yapı değişikliği yok.
- Uç durumlar denendi: ilk ve son dönem, boş değerler, toplam satırı, filtre kombinasyonları.
- Her ölçünün açıklaması dolu; veri sözlüğü güncel.
- Satır düzeyi güvenlik her rolle test edildi.
- Sayfa, Performans Analizi’nde (Performance analyzer) kabul edilebilir sürede açılıyor.
- Erişilebilirlik ve mobil düzen kontrol edildi (“Mobil düzen, erişilebilirlik, dışa aktarma ve kişiselleştirme” dersi).
- Sürüm notu yazıldı, kullanıcılara duyuru hazır.