fix(veri): tadımlık örneği canlı tabanı gösterir; sunucudan gelen liste riskleri yeniden hesaplanır

Yayın sonrası denetim (2026-09-21):
- tadımlık havuzu snapshot'ı 2025 tabanını taşıyordu: örnek satır 'Tıp ~5.118,
  az riskli' derken aynı sayfadaki tablo 4.481 gösteriyordu. Taban ve sıra
  geçmişi artık okuma anında canlı DB'den; güncel kılavuzdan çıkmış program
  örnek gösterilmez (sıradaki kategoriye düşülür)
- sunucuylaBirlestir riskleri her zaman yeniler: sunucu kaydı taze taban +
  başka cihazın bayat riskini taşıyabiliyordu

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-21 20:06:35 +03:00
parent 49683fa113
commit 3cf8ec94a0
3 changed files with 27 additions and 5 deletions

View File

@@ -152,9 +152,11 @@ export function sunucuylaBirlestir(sunucuItems: ManuelTercih[]): ManuelTercih[]
liste = [...liste, ...ekler].slice(0, MANUEL_LISTE_MAX);
kaydet();
yayinla();
// Başka cihazda profilsiz eklenmiş kayıtlar risksiz gelir; profil lokalde
// zaten varsa PROFIL_DEGISTI_EVENT yayılmaz, riski burada doldur.
if (liste.some((t) => t.risk == null)) riskleriYenile();
// Sunucudan gelen kayıtların riski başka cihazın o günkü tabanına göredir
// (ya da profilsiz eklendiyse hiç yoktur); sunucu tabanı tazeler ama riski
// yenilemez. Profil lokalde varsa hepsini güncel tabanla yeniden hesapla
// (profil yoksa riskleriYenile zaten işlem yapmaz).
riskleriYenile();
return liste;
}

View File

@@ -210,6 +210,14 @@ export function netlerGetir(programId: string): ProgramNetSatiri[] {
.all(programId) as ProgramNetSatiri[];
}
/** Güncel kılavuzdaki tek program; arşivlenmiş ya da bilinmeyen id'de null. */
export function programGetir(id: string): Program | null {
const row = getDb()
.prepare(`SELECT ${SELECT_COLS} FROM programs WHERE id = ?`)
.get(id) as ProgramHamSatiri | undefined;
return row ? programSatiri(row) : null;
}
/**
* Kayıtlı manuel liste satırlarının güncel efektif sırası (son yıl, yoksa bir
* önceki). Kayıtlar efektif sırayı ekleme anının snapshot'ı olarak taşır; yeni

View File

@@ -10,7 +10,8 @@ import type { Dilim } from "./rapor-havuzu";
import type { RaporSonuc } from "@/features/rapor/types/rapor";
import { dilimdenRisk, riskHesapla, riskNotuMetni } from "./risk";
import { trendOzetiMetni } from "./trend";
import { VERI_YIL_SAYISI } from "./veri-yillari";
import { ILK_YIL, VERI_YIL_SAYISI } from "./veri-yillari";
import { programGetir } from "./db";
/** Sihirbaz kategorisi seçilmemiş kullanıcı için kova×tür başına fallback satır. */
export const GENEL_KATEGORI = "genel";
@@ -123,7 +124,18 @@ export async function tadimlikSec(
),
});
if (satir && gerekceServisEdilebilir(satir.gerekce)) {
const program = satir.program as RaporSonuc["programlar"][string];
// Havuz batch'te üretilir ve yeni yerleştirme yılı yüklenince bayatlar:
// snapshot'taki taban/geçmiş yerine CANLI veri servis edilir ki örnek
// satır aynı sayfadaki tabloyla çelişmesin. Güncel kılavuzdan çıkmış
// (arşivlenmiş) program örnek gösterilmez — sıradaki kategoriye düşülür.
const canli = programGetir(satir.programId);
if (!canli) continue;
const program: RaporSonuc["programlar"][string] = {
...(satir.program as RaporSonuc["programlar"][string]),
efektifSira: canli.efektifSira,
siraGecmisi: canli.siraGecmisi,
ilkYil: ILK_YIL,
};
return {
programId: satir.programId,
dilim: satir.dilim,