fix(veri): yanlış DEVLET etiketi kalıcı onarım + baz ad çelişki denetimi

3 kurum (Kıbrıs Amerikan, Uluslararası Balkan, Uluslararası Saraybosna)
kaynak CSV'den `unitur='DEVLET'` geliyordu. `db.ts:79-82` filtreleri
yüzünden "devlet üniversitesi istiyorum" diyen öğrencinin aday havuzuna
27 KKTC/yurt dışı programı sızıyor, "vakıf" diyende aynı 27'si eksik
kalıyordu. Kullanıcının fark edemeyeceği bir doğruluk hatasıydı.

unitur-onar.ts — Aşama D (KURUM_DUZELT):
  A/B/C yalnız `unitur IS NULL` satırlara dokunuyordu; bu satırlar NULL
  değil, DOLU ve YANLIŞ. D koşulsuz çalışır ve Aşama A'dan ÖNCE koşar ki
  yanlış değer başka satırlara kopyalanmasın. İdempotent (2. koşu: 0/0).
  Her düzeltmenin kanıtı kurumun YÖK Atlas'taki kendi parantezli ikinci
  yazımı: "(ÜSKÜP-MAKEDONYA)" → YURTDISI KAMU, "(KKTC-LEFKOŞA)" → KKTC.
  refresh.ts:519 `uniturSec` DB'deki değeri kopyaladığı için düzeltme
  buraya yazılınca her tazelemede kalıcı olur.

veri-kalite.ts — iki yeni ZORUNLU kontrol (dosyanın sonuna):
  13. "baz ad başına tek unitur" — kök neden buydu: unitur-onar.ts'in
      eski çelişki koruması GROUP BY universite (TAM ad) ile çalıştığı
      için aynı kurumun iki yazımı arasındaki DEVLET↔YURTDISI KAMU
      çelişkisini hiç görmüyordu.
  14. "DEVLET etiketi Türkiye ili ile destekli" — 13'ün kör noktası:
      Kıbrıs Amerikan'ın İKİ yazımı da yanlış etiketli olduğu için
      ortada çelişki yok. 13 tek başına 100 satırın yalnız 58'ini
      koruyordu. Şartnamenin ötesinde, gerekçesi raporun §4'ünde.

Doğrulama: düzeltme öncesi DB'de iki kontrol de KALDI (çıkış kodu 1);
sonrasında 0 ZORUNLU kaldı, 3 uyarı (üçü de önceden vardı). Tek satır
bilerek bozulduğunda ikisi de yakaladı. tsc + eslint temiz.

Veri (126 satır) ayrı commit'te. Rapor: docs/gece-vardiyasi/2026-09-22/
09-p2-unitur.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-23 00:24:42 +03:00
parent 9bd448bd16
commit b66c720b32
3 changed files with 254 additions and 3 deletions

View File

@@ -21,6 +21,7 @@ import { EFEKTIF_SIRA_SQL, ILK_YIL } from "../src/lib/veri-yillari";
import { EFEKTIF_INDEKS, efektifSorguPlani } from "./db-index";
import { kimlikFarklari, onarimKayitlari, yilKolonlari, type DbKimlik } from "./kimlik";
import { hamOku, sonHamDosya, TUR_MAP } from "./refresh";
import { KKTC_ILLERI } from "./unitur-onar";
import {
argOku,
bayrakVar,
@@ -291,6 +292,46 @@ async function main() {
console.log(` şimdi, tüm satırlar (yeni dahil) : ${toplamlar(simdi)}`);
}
// 13. Aynı kurumun iki yazımı arasında unitur çelişkisi — BAZ AD üzerinden.
// unitur-onar.ts'in eski çelişki koruması GROUP BY universite (TAM ad) ile
// çalıştığı için "X ÜNİVERSİTESİ" ve "X ÜNİVERSİTESİ (ÜSKÜP-MAKEDONYA)" iki
// ayrı kurum sayılıyor, aralarındaki DEVLET↔YURTDISI KAMU çelişkisi hiç
// görünmüyordu. Baz ad = sondaki parantezli ek atılmış hâl.
const BAZ_AD =
"TRIM(CASE WHEN instr(universite, '(') > 0 THEN substr(universite, 1, instr(universite, '(') - 1) ELSE universite END)";
const bazAdCeliskileri = `(SELECT ${BAZ_AD} AS bazAd, GROUP_CONCAT(DISTINCT unitur) AS turler, COUNT(*) AS adet,
MAX(unitur = 'DEVLET') <> MIN(unitur = 'DEVLET') AS devletBolunmus
FROM programs WHERE unitur IS NOT NULL GROUP BY 1 HAVING COUNT(DISTINCT unitur) > 1)`;
const bolunmus = ornek(`SELECT bazAd, turler, adet FROM ${bazAdCeliskileri} WHERE devletBolunmus`);
zorunlu(
"baz ad başına tek unitur",
bolunmus === "",
bolunmus === ""
? "aynı kurumun iki yazımı devlet/vakıf filtresini bölmüyor"
: `devlet filtresine giren, vakıf filtresinden düşen kurum: ${bolunmus} → scripts/unitur-onar.ts KURUM_DUZELT`
);
const esdegerFark = ornek(`SELECT bazAd, turler, adet FROM ${bazAdCeliskileri} WHERE NOT devletBolunmus`);
bilgi("baz ad unitur farkı (devlet/vakıf ayrımını bölmeyen)", false, esdegerFark || "yok");
// 14. DEVLET etiketli ama hiçbir programı Türkiye ilinde olmayan kurum.
// 13'ün kör noktası: kurumun İKİ yazımı da yanlış etiketliyse çelişki yoktur.
// Türkiye illerinde tire geçmez; yurt dışı iller tireli (BİŞKEK-KIRGIZİSTAN…),
// KKTC illeri KKTC_ILLERI'nde. İli hiç olmayan kurumlar (MSB/İçişleri) hariç.
const yurtDisiDevlet = ornek(
`SELECT universite, GROUP_CONCAT(DISTINCT il), COUNT(*) FROM programs
WHERE unitur = 'DEVLET' GROUP BY universite
HAVING SUM(il IS NOT NULL) > 0
AND SUM(il NOT LIKE '%-%' AND il NOT IN (${KKTC_ILLERI.map(() => "?").join(",")})) = 0`,
...KKTC_ILLERI
);
zorunlu(
"DEVLET etiketi Türkiye ili ile destekli",
yurtDisiDevlet === "",
yurtDisiDevlet === ""
? "DEVLET etiketli her kurumun en az bir programı Türkiye ilinde"
: `tüm programları KKTC/yurt dışında olduğu hâlde DEVLET: ${yurtDisiDevlet}`
);
db.close();
console.log(`\nSonuç: ${basarisiz} ZORUNLU kontrol kaldı, ${uyari} uyarı.`);
if (basarisiz > 0) process.exit(1);