80 lines
3.5 KiB
JavaScript
80 lines
3.5 KiB
JavaScript
/**
|
||
* Ortak kalem havuzu istemcisi.
|
||
*
|
||
* Teklif cetveli kalemleri EKAP API'sinde yok (doküman sayfası CAPTCHA ile
|
||
* korunuyor). Bir kullanıcı dokümanı yükleyince kalemler havuza yazılıyor ve
|
||
* o ihale herkesin kartında kalemleriyle görünüyor.
|
||
*/
|
||
import { getToken } from './auth.js';
|
||
|
||
/** Bir ihalenin tüm kalemleri. */
|
||
export async function kalemleriGetir(ikn, {signal, timeoutMs = 30000} = {}) {
|
||
const controller = new AbortController();
|
||
const cancel = () => controller.abort();
|
||
if (signal?.aborted) cancel(); else signal?.addEventListener('abort',cancel,{once:true});
|
||
let timedOut = false;
|
||
const timer = setTimeout(() => {timedOut=true;controller.abort();},timeoutMs);
|
||
try {
|
||
const r = await fetch(`/api/kalem?ikn=${encodeURIComponent(ikn)}`,{signal:controller.signal});
|
||
const d = await r.json().catch(() => null);
|
||
if (!r.ok || d?.success !== true || !Array.isArray(d.kalemler)) throw new Error('Kalem listesi alınamadı. Yeniden deneyin.');
|
||
return d;
|
||
} catch (error) {
|
||
if (timedOut) throw new Error('Kalem listesi yüklenirken zaman aşımı oluştu.');
|
||
throw error;
|
||
} finally {clearTimeout(timer);signal?.removeEventListener('abort',cancel);}
|
||
}
|
||
|
||
/** Kalem metninde arama — eşleşen İKN'ler. */
|
||
export async function kalemAra(q,{signal,timeoutMs=30000}={}) {
|
||
const controller=new AbortController();
|
||
const cancel=()=>controller.abort();
|
||
if(signal?.aborted)cancel();else signal?.addEventListener('abort',cancel,{once:true});
|
||
let timedOut=false;
|
||
const timer=setTimeout(()=>{timedOut=true;controller.abort();},timeoutMs);
|
||
try {
|
||
const r=await fetch(`/api/kalem/ara?q=${encodeURIComponent(q)}`,{signal:controller.signal});
|
||
const d=await r.json().catch(()=>null);
|
||
if(!r.ok || d?.success!==true || !Array.isArray(d.sonuclar))throw new Error('Doküman kalemlerinde arama tamamlanamadı.');
|
||
return d.sonuclar;
|
||
} catch(error) {
|
||
if(timedOut)throw new Error('Doküman kalemlerinde arama zaman aşımına uğradı.');
|
||
throw error;
|
||
} finally {clearTimeout(timer);signal?.removeEventListener('abort',cancel);}
|
||
}
|
||
|
||
/**
|
||
* Tarayıcıda çıkarılmış metinden (PDF) kalem ayrıştırıp havuza yazar.
|
||
* docx/xlsx/zip yüklemede sunucu bunu zaten kendisi yapıyor.
|
||
*/
|
||
export async function kalemCikar({ ikn, metin, dosya, documentId }) {
|
||
const r = await fetch('/api/kalem/cikar', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${getToken()}` },
|
||
body: JSON.stringify({ ikn, metin, dosya, documentId }),
|
||
});
|
||
const d = await r.json().catch(() => ({}));
|
||
if (!d.success) throw new Error(d.error || 'kalem çıkarılamadı');
|
||
return d;
|
||
}
|
||
|
||
/**
|
||
* Doküman metninden İKN — toplu yüklemede PDF tarayıcıda okunduğu için
|
||
* sunucudaki kalem-cikar.mjs#iknCikar'ın istemci eşi.
|
||
*/
|
||
export function iknCikar(metin) {
|
||
const duz = String(metin || '').slice(0, 20000).toLocaleLowerCase('tr-TR')
|
||
.replace(/ı/g, 'i').replace(/ş/g, 's').replace(/ğ/g, 'g').replace(/ç/g, 'c').replace(/ö/g, 'o').replace(/ü/g, 'u');
|
||
const m = /ihale\s+kayit\s+numarasi\s*(?:\(\s*ikn\s*\))?\s*:?\s*(\d{4}[/-]\d{3,8})/.exec(duz)
|
||
|| /\bikn\s*[:=]?\s*(\d{4}[/-]\d{3,8})/.exec(duz);
|
||
return m ? m[1].replace('-', '/') : null;
|
||
}
|
||
|
||
/** OKAS kataloğunda ad ile arama — "ortoped" → 33141700 Ortopedik malzemeler */
|
||
export async function okasAra(q) {
|
||
const r = await fetch(`/api/okas/ara?q=${encodeURIComponent(q)}`);
|
||
const d = await r.json().catch(() => ({}));
|
||
if (!d.success) throw new Error(d.error || 'OKAS araması başarısız');
|
||
return d.kalemler || [];
|
||
}
|