feat: derin analiz & yol haritasi + ihale dosyasi hazirlama; docx/xlsx/zip okunuyor
Doküman panelindeki "Tum Evraki Derin Analiz Et" dugmesi EKAP ilan metnini ve
ihaleye yuklenmis butun belgeleri TEK metinde birlestirip gonderiyor; model
sartnameyi ilanla ve eklerle capraz okuyabiliyor.
Derin analiz (mode='derin', ayri sistem istemi + 8000 token):
- Teklifi gecersiz kilabilecek noktalar (kirmizi uyari, en ustte)
- Gozden kacan ince detaylar (Kritik/Yuksek/Orta + madde no + neden onemli)
- Alinacak kalemler: aranan evsaflar, miktar, sartnamede geciyorsa fiyat
(modele "TAHMIN URETME" talimati verildi, yoksa null)
- Belge kontrol listesi, kritik tarihler, maliyet kalemleri
- Teklife kadar yol haritasi (faz / kim / ne zaman / cikti)
- Idareye sorulacak belirsizlikler
Standart hizli ozet modu aynen duruyor.
Ihale Dosyasi Hazirla (rapor sonunda, acilir bolum):
- Eksik firma bilgileri kullaniciya sorulur, profilden gelenler sorulmaz,
girilenler tarayicida saklanir
- Kalem fiyatlandirma tablosu, canli toplam + yaziyla karsiligi
- Teklif Mektubu, Birim Fiyat Teklif Cetveli, Evrak Kontrol Listesi
- Belgeler yazdirilabilir HTML: jsPDF'in gomulu fontlari WinAnsi, s/g/i/I
tasimiyor (bkz. services/pdf.js ASCII basliklari) — resmi teklif mektubunda
bozuk Turkce kabul edilemez
docx/xlsx/zip metin cikarimi (server/office-text.mjs):
- ihaleab projesindeki officeText.ts'ten tasindi, harici bagimlilik yok
- Sunucuda: tarayicida cozucu yok, baytlar zaten BELGE_DIR'de
- Tablolar " | " ile korunuyor, ic ice zip aciliyor, ~$ gecici dosyalari atlanir
- Yeni uc: GET /api/me/documents/text
- Yukleme kabul listesi .doc/.rar cikarildi (karsiligi yok), .xlsx eklendi
fix: yuklenen belgelerdeki "AI analiz" dugmesi bozuktu — extractText nesne
donduruyor ({text,pageCount,usedPages}), kod onu duz metin sanip gonderiyordu;
sunucuya "[object Object]" gidiyor ve analiz reddediliyordu. Uzunluk kontrolu
de nesne uzerinde undefined verdigi icin hatayi yutuyordu.
fix: analiz dokuman panelinden baslatildiginda modal kendi isAnalyzing'ini
bilmiyordu, kullanici 1-2 dakika bos modal goruyordu — ortak aiAnalyzing sinyali
This commit is contained in:
@@ -21,6 +21,7 @@ import { SECTOR_RULES, INSTITUTION_RULES, classify, sektorBul, SEKTOR_ETIKETLERI
|
||||
import { loginWithGoogle, userFromAuthHeader } from './auth.mjs';
|
||||
import { emailConfigured, sendEmail, tenderDigestHtml, emailFrom } from './email.mjs';
|
||||
import { aiConfigured, availableProviders, analyzeSpec } from './ai.mjs';
|
||||
import { arsivMetni, sunucuOkuyabilir } from './office-text.mjs';
|
||||
import { classifyTenderCpv, classifyCpvByKeyword } from './cpv-classify.mjs';
|
||||
import { billingConfigured, webhookConfigured, planCatalog, createCheckoutSession, verifyWebhook, planForPrice, cancelSubscription, IPTAL_NEDENLERI } from './billing.mjs';
|
||||
import * as store from './user-store.mjs';
|
||||
@@ -786,6 +787,24 @@ const server = http.createServer(async (req, res) => {
|
||||
return json(res, 500, { success: false, error: 'dosya okunamadı' });
|
||||
}
|
||||
}
|
||||
// Belge metni — docx/xlsx/zip için. PDF tarayıcıda (pdfjs) okunuyor;
|
||||
// bu türler için tarayıcıda çözücü yok, baytlar zaten burada duruyor.
|
||||
if (url.pathname === '/api/me/documents/text') {
|
||||
const user = userFromAuthHeader(req.headers['authorization']);
|
||||
if (!user) return json(res, 401, { success: false, error: 'oturum yok' });
|
||||
const rec = store.getDocument(user.email, url.searchParams.get('id'));
|
||||
if (!rec) return json(res, 404, { success: false, error: 'belge bulunamadı' });
|
||||
if (!sunucuOkuyabilir(rec.ad)) {
|
||||
return json(res, 400, { success: false, error: 'Bu dosya türünden sunucuda metin çıkarılamıyor (docx, xlsx, zip destekleniyor).' });
|
||||
}
|
||||
try {
|
||||
const buf = fs.readFileSync(path.join(store.BELGE_DIR, rec.dosya));
|
||||
const metin = arsivMetni(rec.ad, buf);
|
||||
return json(res, 200, { success: true, ad: rec.ad, metin, karakter: metin.length });
|
||||
} catch (e) {
|
||||
return json(res, 422, { success: false, error: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
// --- Kullanıcı verisi (localStorage yerine sunucu tarafı) ---
|
||||
if (url.pathname.startsWith('/api/me/data')) {
|
||||
@@ -973,6 +992,7 @@ const server = http.createServer(async (req, res) => {
|
||||
fileName: body.fileName,
|
||||
tender: body.tender,
|
||||
chain: body.chain,
|
||||
mode: body.mode === 'derin' ? 'derin' : undefined,
|
||||
});
|
||||
return json(res, 200, { success: true, ...out, analyzedAt: new Date().toISOString() });
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user