kullanicininRaporu dönmeden önce programOzellikleriGetir ile 24 id tek sorguda okunur, programlar[id].varyant yazılır; eski kayıtlar da kazanır, app.db'ye yazılmaz. Rapor listesi tür çipinin yanında SATIR_CIP ile gösterir. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
78 lines
3.1 KiB
TypeScript
78 lines
3.1 KiB
TypeScript
import "server-only";
|
||
import { desc, eq, sql } from "drizzle-orm";
|
||
import { appDb, schema } from "@/lib/appdb";
|
||
import { anahtarVar } from "@/lib/ai/client";
|
||
import { programOzellikleriGetir } from "@/lib/program-ozellik";
|
||
import { varyantEtiketi } from "@/lib/program-varyant";
|
||
import type { RaporSonuc } from "./types/rapor";
|
||
|
||
// Rapor feature'ının sorgu kapısı: kayıtlı rapor, sohbet geçmişi ve girişsiz
|
||
// tadımlık seçimi buradan okunur.
|
||
|
||
// Girişsiz tadımlık satırı — batch üretilmiş havuzdan seçilir, LLM'e gitmez.
|
||
export { tadimlikSec } from "@/lib/tadimlik-havuzu";
|
||
|
||
// Kullanıcının kayıtlı raporunu okuyan TEK kapı. Rapor tablosunu okuyan her
|
||
// yer (sayfalar, action'lar, soru API'si) buradan geçmeli; doğrudan
|
||
// appDb.query.reports.findFirst kullanma.
|
||
//
|
||
// Neden: dev'de API anahtarı yokken üretilen mock rapor DB'ye kaydediliyor
|
||
// (akışın tamamı anahtarsız test edilebilsin diye — bilinçli). Ama anahtar
|
||
// sonradan eklenince kullanıcı başına tek rapor kuralı yüzünden o bayat mock,
|
||
// gerçek Yapay Zeka çıktısıymış gibi servis edilmeye devam ediyordu. Gerçek AI
|
||
// aktifken mock üretimi bir rapor "yok" sayılır; kullanıcı yeni (gerçek)
|
||
// listeyi üretir ve kayıt üzerine yazılır.
|
||
|
||
function bayatMockMu(sonuc: RaporSonuc): boolean {
|
||
const mockUretimi =
|
||
sonuc.devMock === true ||
|
||
// devMock alanı eklenmeden önce kaydedilmiş mock raporlar
|
||
sonuc.genelDegerlendirme?.startsWith("(Dev mock");
|
||
if (!mockUretimi) return false;
|
||
const mockHalaAktif =
|
||
process.env.NODE_ENV !== "production" && !anahtarVar();
|
||
return !mockHalaAktif;
|
||
}
|
||
|
||
export async function kullanicininRaporu(userId: string) {
|
||
const satir = await appDb.query.reports.findFirst({
|
||
where: eq(schema.reports.userId, userId),
|
||
});
|
||
if (satir?.result && bayatMockMu(satir.result as RaporSonuc)) return null;
|
||
if (satir?.result) varyantlariEkle(satir.result as RaporSonuc);
|
||
return satir ?? null;
|
||
}
|
||
|
||
// Kayıtlı raporun program satırlarına burs/dil/öğretim türü etiketi (okuma
|
||
// anında, tek sorgu): rapor JSON'u üretim anında bunu taşımıyor, eski
|
||
// kayıtlar da bu yoldan kazanır. yokatlas.db salt okunur; app.db'ye yazılmaz.
|
||
function varyantlariEkle(sonuc: RaporSonuc): void {
|
||
const idler = Object.keys(sonuc.programlar ?? {});
|
||
if (idler.length === 0) return;
|
||
const ozellikler = programOzellikleriGetir(idler);
|
||
for (const id of idler) {
|
||
const o = ozellikler[id];
|
||
sonuc.programlar[id].varyant = o ? varyantEtiketi(o) : null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Kullanıcının danışman sohbet geçmişi: en YENİ 100 mesaj, eskiden yeniye.
|
||
* created_at saniye çözünürlüklü; aynı saniyedeki soru-cevap sırası rowid ile
|
||
* korunur.
|
||
*/
|
||
export async function sohbetGecmisiGetir(userId: string) {
|
||
const satirlar = await appDb
|
||
.select({
|
||
id: schema.chatMessages.id,
|
||
role: schema.chatMessages.role,
|
||
content: schema.chatMessages.content,
|
||
meta: schema.chatMessages.meta,
|
||
})
|
||
.from(schema.chatMessages)
|
||
.where(eq(schema.chatMessages.userId, userId))
|
||
.orderBy(desc(schema.chatMessages.createdAt), sql`rowid DESC`)
|
||
.limit(100);
|
||
return satirlar.reverse();
|
||
}
|