feat: urun arama — urun adini ihale DOKUMANLARININ icinde aratir
saidsurucu/ihale-mcp deposu incelenirken EKAP arama API'sinin doküman ici arama parametreleri oldugu goruldu: teklifCetvelindeAra, teknikSartnamedeAra, idariSartnamedeAra, sozlesmeTasarisindaAra. EKAP dokumani kendi tarafinda indeksliyor — yani teklif cetvelinde arama icin dokumani indirmeye (ve CAPTCHA'ya) gerek yok. Kullanicinin sikayetini olcen kanit: ELDIVEN basliкta 1.135 → teklif cetvelinde 29.057 ORTOPEDIK VIDA baslikta 0 → teklif cetvelinde 3 HEMOGRAM baslikta 283 → teklif cetvelinde 2.529 "ORTOPEDIK VIDA" hicbir ihale BASLIGINDA gecmiyor; gectigi ihalelerin adi "VETERINER ILAC ... SARF MALZEME". Basliga bakan firma bunlari bulamiyordu. - ekap-v2.mjs: searchBody artik opts.kapsam ile daraltilabiliyor; searchInDocuments() yalnizca teklif cetvelinde (istege bagli teknik sartnamede) arar ve sonucu normalize eder - GET /api/urun-ara?q=&skip=&take=&teknik= — 5 dk bellek onbellegi ile (EKAP'a uzak cagri, ayni sorgu kaynagi yormasin) - Header'da "URUN ARA" dugmesi + UrunAramaModal: sayfalama, "sadece teklif verilebilir" suzgeci, havuzda acik olan ihalede detayi acma kisayolu SINIR: EKAP hangi kalemin eslestigini dondurmuyor, yalnizca eslesen ihaleleri. Kalem dokumu icin dokuman yuklemeye dayali ortak havuz yolu gecerli kaliyor; arayuzde bu acikca yaziliyor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,10 @@ import { emailConfigured, sendEmail, tenderDigestHtml, emailFrom } from './email
|
||||
import { aiConfigured, availableProviders, analyzeSpec } from './ai.mjs';
|
||||
import { arsivMetni, sunucuOkuyabilir } from './office-text.mjs';
|
||||
import { kalemleriCikar } from './kalem-cikar.mjs';
|
||||
import { searchInDocuments } from './ekap-v2.mjs';
|
||||
|
||||
// Ürün araması EKAP'a uzak çağrı yapar; aynı sorgu tekrarlanırsa kaynağı yorma.
|
||||
const urunAramaCache = new Map();
|
||||
import * as kalemStore from './kalem-store.mjs';
|
||||
import { classifyTenderCpv, classifyCpvByKeyword } from './cpv-classify.mjs';
|
||||
import { billingConfigured, webhookConfigured, planCatalog, createCheckoutSession, verifyWebhook, planForPrice, cancelSubscription, IPTAL_NEDENLERI } from './billing.mjs';
|
||||
@@ -751,6 +755,31 @@ const server = http.createServer(async (req, res) => {
|
||||
const sonuc = kalemStore.kalemAra(q);
|
||||
return json(res, 200, { success: true, adet: sonuc.length, sonuclar: sonuc });
|
||||
}
|
||||
// --- Ürün araması: metni ihale DOKÜMANININ içinde arar ---
|
||||
// EKAP teklif cetvelini kendi tarafında indeksliyor; doküman indirmeye
|
||||
// gerek yok. "ORTOPEDİK VİDA" hiçbir başlıkta geçmiyor ama teklif
|
||||
// cetvellerinde geçiyor — firmanın kendi ürününü bulma yolu bu.
|
||||
if (url.pathname === '/api/urun-ara') {
|
||||
const q = (url.searchParams.get('q') || '').trim();
|
||||
if (q.length < 3) return json(res, 400, { success: false, error: 'en az 3 karakter' });
|
||||
const skip = Math.max(0, Number(url.searchParams.get('skip')) || 0);
|
||||
const take = Math.min(50, Math.max(1, Number(url.searchParams.get('take')) || 20));
|
||||
const teknik = url.searchParams.get('teknik') === '1';
|
||||
const anahtar = `${q}|${skip}|${take}|${teknik}`;
|
||||
const simdi = Date.now();
|
||||
const onbellek = urunAramaCache.get(anahtar);
|
||||
if (onbellek && simdi - onbellek.zaman < 5 * 60 * 1000) {
|
||||
return json(res, 200, { success: true, onbellekten: true, ...onbellek.veri });
|
||||
}
|
||||
try {
|
||||
const out = await searchInDocuments(q, { teknikSartname: teknik, skip, take });
|
||||
urunAramaCache.set(anahtar, { zaman: simdi, veri: out });
|
||||
if (urunAramaCache.size > 200) urunAramaCache.delete(urunAramaCache.keys().next().value);
|
||||
return json(res, 200, { success: true, ...out });
|
||||
} catch (e) {
|
||||
return json(res, 502, { success: false, error: e.message });
|
||||
}
|
||||
}
|
||||
if (url.pathname === '/api/health/kalem') {
|
||||
return json(res, 200, { success: true, ...kalemStore.kalemSayilari(), depo: kalemStore.available() });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user