diff --git a/src/controllers/case.controller.ts b/src/controllers/case.controller.ts index 73f6059..f5de7d4 100644 --- a/src/controllers/case.controller.ts +++ b/src/controllers/case.controller.ts @@ -1,7 +1,7 @@ import { Response } from 'express'; import { supabase } from '../lib/supabase'; import { AuthenticatedRequest } from '../middleware/auth'; -import { runIddianameAnalysis, runCaseNarrativeAnalysis, runStatementAnalysis, runDeficiencyAnalysis, runStrategyAnalysis } from './document.controller'; +import { runIddianameAnalysis, runCaseNarrativeAnalysis, runStatementAnalysis, runDeficiencyAnalysis, runStrategyAnalysis, runMediationAnalysis } from './document.controller'; import { findOrCreateCaseByTitle } from '../lib/caseLookup'; export const createCase = async (req: AuthenticatedRequest, res: Response) => { @@ -277,6 +277,60 @@ export const analyzeStrategy = async (req: AuthenticatedRequest, res: Response) } }; +export const analyzeMediation = async (req: AuthenticatedRequest, res: Response) => { + try { + const { caseId } = req.params; + const { clientName } = req.body; + + if (!caseId) { + return res.status(400).json({ error: 'Geçersiz caseId' }); + } + + if (!clientName) { + return res.status(400).json({ error: 'clientName (Müvekkil Adı) zorunludur' }); + } + + const { data: docs, error: docsError } = await supabase + .from('documents') + .select('filename, extracted_text') + .eq('case_id', caseId) + .order('uploaded_at', { ascending: true }); + if (docsError) throw docsError; + + const trashKeywords = ['tebligat', 'makbuz', 'pul', 'zarf', 'masraf', 'havale', 'barkod', 'alındı', 'görüldü', 'ilan', 'talimat', 'nüfus', 'sicil', 'sabıka']; + const targetDocs = (docs || []).filter(d => { + if (!d.extracted_text || !String(d.extracted_text).trim()) return false; + const fn = (d.filename || '').toLowerCase().replace(/ı/g, 'i').replace(/ğ/g, 'g').replace(/ü/g, 'u').replace(/ş/g, 's').replace(/ö/g, 'o').replace(/ç/g, 'c'); + return !trashKeywords.some(kw => fn.includes(kw)); + }); + + if (targetDocs.length === 0) { + return res.status(400).json({ error: 'Bu dosyada arabuluculuk analizi yapılabilecek evrak bulunamadı.' }); + } + + const perDocLimit = Math.max(1000, Math.floor(25000 / targetDocs.length)); + const combinedText = targetDocs + .map((d) => `--- ${d.filename} ---\n${String(d.extracted_text).slice(0, perDocLimit)}`) + .join('\n\n'); + + const analysisInput = `Aşağıdaki belgeler dava dosyasına aittir:\n\n${combinedText}`; + + const { summaryJson, aiModel } = await runMediationAnalysis(analysisInput, clientName); + + const { data: analysisRecord, error: analysisError } = await supabase + .from('analyses') + .insert([{ case_id: caseId, document_id: null, summary_json: { mediationAnalysis: summaryJson, clientName }, analysis_type: 'mediation', model_used: aiModel }]) + .select() + .single(); + if (analysisError) throw analysisError; + + res.json({ analysis: analysisRecord }); + } catch (error: any) { + console.error('Analyze Mediation Error:', error); + res.status(500).json({ error: error.message || 'Internal Server Error' }); + } +}; + // UYAP Evrak İndirici eklentisinin "Taraf Bilgileri" sekmesinden yakaladığı // davacı/davalı/sanık + vekil bilgisini kaydeder. AI'nin OCR metninden tahmin // ettiği "Taraflar" alanından çok daha güvenilir — doğrudan UYAP'ın yapılandırılmış diff --git a/src/controllers/document.controller.ts b/src/controllers/document.controller.ts index 6cb4bbd..e351929 100644 --- a/src/controllers/document.controller.ts +++ b/src/controllers/document.controller.ts @@ -175,6 +175,27 @@ Sadece ve sadece JSON döndür, kod bloğu işareti (\`\`\`) veya başka bir aç return { summaryJson: resultJson, aiModel }; } +export async function runMediationAnalysis(combinedText: string, clientName: string): Promise<{ summaryJson: any; aiModel: string }> { + const prompt = `Sen uzman bir müzakereci ve arabuluculuk asistanısın. Aşağıda sunulan dava dosyasındaki evrakları detaylıca inceleyerek, müvekkilimiz "${clientName}" perspektifinden davanın kazanılma olasılığını ve en uygun pazarlık marjını hesaplayacaksın. + +Dosyadaki delilleri, iddiaları ve varsa zayıf noktaları objektif bir şekilde değerlendir. Yargılama giderleri, avukatlık ücretleri ve sürecin uzunluğunu göz önüne alarak masada anlaşılabilecek "karlı" bir matematiksel/hukuki pazarlık marjı sun. + +Çıktıyı KESİNLİKLE aşağıdaki geçerli JSON formatında ver: +{ + "winProbability": "Örn: %60", + "riskAnalysis": [ + "Davanın kaybedilmesine veya uzamasına neden olabilecek risk 1" + ], + "negotiationMargin": "Önerilen pazarlık aralığı ve gerekçesi (Örn: X TL ile Y TL arası makuldür çünkü yargılama giderleri Z TL tutacaktır.)", + "strategy": "Arabuluculuk masasında veya müzakerede kullanılacak temel psikolojik/hukuki argüman (1-2 paragraf)." +} + +Sadece ve sadece JSON döndür, kod bloğu işareti (\`\`\`) veya başka bir açıklama ekleme.`; + + const { resultJson, aiModel } = await callAiModel(prompt, combinedText); + return { summaryJson: resultJson, aiModel }; +} + export async function runDeficiencyAnalysis(combinedText: string): Promise<{ summaryJson: any; aiModel: string }> { const { resultJson, aiModel } = await callAiModel(DEFICIENCY_ANALYSIS_SYSTEM_PROMPT, combinedText); return { summaryJson: resultJson, aiModel }; diff --git a/src/routes/case.routes.ts b/src/routes/case.routes.ts index cbf9888..e04e4ab 100644 --- a/src/routes/case.routes.ts +++ b/src/routes/case.routes.ts @@ -1,6 +1,6 @@ import { Router } from 'express'; import { requireAuth } from '../middleware/auth'; -import { createCase, deleteCase, summarizeCase, updateCaseParties, analyzeStatements, analyzeDeficiencies, analyzeStrategy } from '../controllers/case.controller'; +import { createCase, deleteCase, summarizeCase, updateCaseParties, analyzeStatements, analyzeDeficiencies, analyzeStrategy, analyzeMediation } from '../controllers/case.controller'; const router = Router(); @@ -10,6 +10,7 @@ router.post('/:caseId/summarize', requireAuth, summarizeCase); router.post('/:caseId/analyze-statements', requireAuth, analyzeStatements); router.post('/:caseId/analyze-deficiencies', requireAuth, analyzeDeficiencies); router.post('/:caseId/analyze-strategy', requireAuth, analyzeStrategy); +router.post('/:caseId/analyze-mediation', requireAuth, analyzeMediation); router.post('/parties', requireAuth, updateCaseParties); export default router;