prefer official EKAP detail deadline
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
import { searchTenders, ekapPost, getIhaleDetay } from './ekap-v2.mjs';
|
||||
import { officialDateFields } from './tender-quality.mjs';
|
||||
|
||||
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36';
|
||||
|
||||
@@ -49,6 +50,7 @@ export async function ilanMetni(ikn) {
|
||||
const t = await findByIkn(ikn);
|
||||
const d = await getIhaleDetay(t.id);
|
||||
const bilgi = d?.ihaleBilgi || {};
|
||||
const officialDate = officialDateFields(bilgi.ihaleTarihSaat);
|
||||
const okas = d?.ihtiyacKalemiOkasList || [];
|
||||
const parcalar = [
|
||||
`İhale adı: ${d?.ihaleAdi || t.ihaleAdi || ''}`,
|
||||
@@ -80,6 +82,7 @@ export async function ilanMetni(ikn) {
|
||||
idareAdi: d?.idareAdi || t.idareAdi,
|
||||
ilanSayisi: ilanlar.length,
|
||||
okasSayisi: okas.length,
|
||||
...officialDate,
|
||||
metin: parcalar.join('\n'),
|
||||
};
|
||||
}
|
||||
|
||||
+3
-2
@@ -10,7 +10,7 @@ import {documentReview,saveDocumentReview,reviewedAnalysisSource} from './docume
|
||||
import { documentMetadataPatch, decodeDocumentUpload } from './document-metadata.mjs';
|
||||
import { deadlineInfo } from '../src/services/tenderCalendar.js';
|
||||
import { exchangeRates } from './exchange-rates.mjs';
|
||||
import { uniqueTenders, announcementFields } from './tender-quality.mjs';
|
||||
import { uniqueTenders, announcementFields, mergeAnnouncementFields } from './tender-quality.mjs';
|
||||
/**
|
||||
* ihaleist API Proxy — ilan.gov.tr canlı ihale verisi
|
||||
*
|
||||
@@ -845,7 +845,8 @@ const server = http.createServer(async (req, res) => {
|
||||
const ikn = url.searchParams.get('ikn');
|
||||
if (!ikn) return json(res, 400, { success: false, error: 'ikn gerekli' });
|
||||
const out = await ilanMetni(ikn);
|
||||
return json(res, 200, { success: true, ...out, ...announcementFields(out.metin) });
|
||||
const parsed = mergeAnnouncementFields(out.metin, out);
|
||||
return json(res, 200, { success: true, ...out, ...parsed, tarih: out.tarih || parsed.tarih || '', saat: out.saat || parsed.saat || '' });
|
||||
} catch (e) {
|
||||
return json(res, 502, sourceUnavailable(e));
|
||||
}
|
||||
|
||||
@@ -48,3 +48,50 @@ export function announcementFields(text) {
|
||||
if (/hizmet alımı\s+4734/i.test(content)) result.alimTuru = 'Kiralama ve Hizmet Alımı';
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* EKAP ihale detayındaki tarih-saat alanını liste ve takvim alanlarına ayırır.
|
||||
* Ayrıştırılamayan/eksik değerler için varsayılan tarih veya saat üretmez.
|
||||
*/
|
||||
export function officialDateFields(value) {
|
||||
const raw = String(value || '').trim();
|
||||
if (!raw) return {};
|
||||
const dotted = raw.match(/(\d{2})\.(\d{2})\.(\d{4})\s*(?:[-–T]|\s)\s*(\d{1,2}):(\d{2})/);
|
||||
if (dotted) return {
|
||||
tarih: `${dotted[1]}.${dotted[2]}.${dotted[3]}`,
|
||||
saat: `${dotted[4].padStart(2, '0')}:${dotted[5]}`,
|
||||
sourceDateTime: raw,
|
||||
};
|
||||
const iso = raw.match(/(\d{4})-(\d{2})-(\d{2})[T\s]+(\d{1,2}):(\d{2})/);
|
||||
if (iso) return {
|
||||
tarih: `${iso[3]}.${iso[2]}.${iso[1]}`,
|
||||
saat: `${iso[4].padStart(2, '0')}:${iso[5]}`,
|
||||
sourceDateTime: raw,
|
||||
};
|
||||
return { sourceDateTime: raw };
|
||||
}
|
||||
|
||||
/**
|
||||
* İlan metninden çıkarılan alanları, resmî EKAP ihale detayındaki alanlarla
|
||||
* birleştirir. Resmî detay tarihi ilan HTML'inden eski/çelişkili bir tarih
|
||||
* gelirse üstün tutulur; fark kullanıcıya açık bir uyarı olarak taşınır.
|
||||
*/
|
||||
export function mergeAnnouncementFields(text, authoritative = {}) {
|
||||
const parsed = announcementFields(text);
|
||||
const sourceTarih = String(authoritative.tarih || '').trim();
|
||||
const sourceSaat = String(authoritative.saat || '').trim();
|
||||
const dateConflict = Boolean(
|
||||
(sourceTarih && parsed.tarih && sourceTarih !== parsed.tarih) ||
|
||||
(sourceSaat && parsed.saat && sourceSaat !== parsed.saat),
|
||||
);
|
||||
const merged = {
|
||||
...parsed,
|
||||
...(sourceTarih ? { tarih: sourceTarih } : {}),
|
||||
...(sourceSaat ? { saat: sourceSaat } : {}),
|
||||
...(authoritative.sourceDateTime ? { sourceDateTime: authoritative.sourceDateTime } : {}),
|
||||
};
|
||||
if (dateConflict) {
|
||||
merged.sourceDateWarning = 'Resmî ihale detay tarihi ile ilan metnindeki tarih farklı; güncel detay tarihi esas alındı.';
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user