refresh EKAP document counts from detail

This commit is contained in:
2026-09-06 19:46:56 +03:00
parent ce072997ac
commit cdf6e988e4
4 changed files with 57 additions and 3 deletions
@@ -282,5 +282,36 @@
], ],
"notes": [ "notes": [
"Aksaray ilan HTML tarihindeki 09.09.2026 değeri ile EKAP ihale detayındaki 16.09.2026 değeri çelişmektedir; uygulama resmî ihale detayını esas alır ve farkı sourceDateWarning ile bildirir." "Aksaray ilan HTML tarihindeki 09.09.2026 değeri ile EKAP ihale detayındaki 16.09.2026 değeri çelişmektedir; uygulama resmî ihale detayını esas alır ve farkı sourceDateWarning ile bildirir."
] ],
"documentLinkChecks": {
"checkedAt": "2026-09-06T16:59:00.000Z",
"scope": "Salt okunur EKAP doküman yönlendirme çağrıları; imzalı URL saklanmadı.",
"cases": [
{
"ikn": "2026/1582991",
"hasUrl": true,
"dokumanSayisi": 0
},
{
"ikn": "2026/1534665",
"hasUrl": true,
"dokumanSayisi": 0
},
{
"ikn": "2026/1499061",
"hasUrl": true,
"dokumanSayisi": 0
},
{
"ikn": "2026/1573235",
"hasUrl": true,
"dokumanSayisi": 1
},
{
"ikn": "2026/1523851",
"hasUrl": true,
"dokumanSayisi": 1
}
]
}
} }
+6
View File
@@ -2296,3 +2296,9 @@ Doğrulama: yeni regresyon 1–81 kodlarının tamamını ve Giresun, Aksaray, I
EKAP ilan metnindeki tarih ile `ihaleBilgi.ihaleTarihSaat` alanı çeliştiğinde resmî ihale detay tarihi artık tek kaynak olarak korunuyor. `officialDateFields` tarih/saat alanını normalize ediyor; `mergeAnnouncementFields` ilan metninin teslimat ve diğer alanlarını korurken resmî tarihi kullanıyor ve farkı `sourceDateWarning` ile bildiriyor. Aksaray `2026/1573235` için detay tarihi `16.09.2026 10:00`, ilan HTML'inde görülen eski değer `09.09.2026 10:00` olarak kanıtlandı. D10 sentetik kabul fixture'ı da güncel resmî tarihe çekildi. EKAP ilan metnindeki tarih ile `ihaleBilgi.ihaleTarihSaat` alanı çeliştiğinde resmî ihale detay tarihi artık tek kaynak olarak korunuyor. `officialDateFields` tarih/saat alanını normalize ediyor; `mergeAnnouncementFields` ilan metninin teslimat ve diğer alanlarını korurken resmî tarihi kullanıyor ve farkı `sourceDateWarning` ile bildiriyor. Aksaray `2026/1573235` için detay tarihi `16.09.2026 10:00`, ilan HTML'inde görülen eski değer `09.09.2026 10:00` olarak kanıtlandı. D10 sentetik kabul fixture'ı da güncel resmî tarihe çekildi.
Doğrulama: `npm test` 299/299 ve üretim derlemesi başarılı. Beş ihale kanıtı [`qa-official-five-tenders.json`](evidence/qa-official-five-tenders.json) içinde tutuluyor; gerçek EKAP doküman indirme ve canlı deployment hâlâ açık. Doğrulama: `npm test` 299/299 ve üretim derlemesi başarılı. Beş ihale kanıtı [`qa-official-five-tenders.json`](evidence/qa-official-five-tenders.json) içinde tutuluyor; gerçek EKAP doküman indirme ve canlı deployment hâlâ açık.
### 2026-09-06 · EKAP doküman yönlendirme ve sayım doğrulaması
Doküman URL'i üretilirken arama yanıtındaki gecikmiş doküman sayısına tek başına güvenilmiyor; güncel ihale detayındaki liste ve bildirilen sayı birlikte değerlendirilerek büyük olan değer kullanılıyor. Beş resmî IKN için yönlendirme çağrısı salt okunur yapıldı ve imzalı URL'ler kanıta kaydedilmedi. Aksaray ve Tepecik detaylarında birer doküman listelendi; diğer üç kayıtta doküman sayısı sıfır döndü ve kullanıcıya EKAP sayfasını açıp kontrol etme akışı korunuyor.
Doğrulama: Beş IKN'de URL üretildi; kanıt [`qa-official-five-tenders.json`](evidence/qa-official-five-tenders.json) içindeki `documentLinkChecks` alanında. Yerel tam test ve üretim derlemesi önceki kontrolde başarılı; canlı deployment ve kullanıcı oturumuyla gerçek indirme kabulü hâlâ açık.
+14 -2
View File
@@ -14,6 +14,12 @@ import { searchTenders, ekapPost, getIhaleDetay } from './ekap-v2.mjs';
import { officialDateFields } from './tender-quality.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'; 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';
const documentCount = (record, fallback = 0) => {
const declared = Number(record?.dokumanSayisi);
const listed = Array.isArray(record?.dokumanListe) ? record.dokumanListe.length : 0;
const fallbackCount = Number(fallback);
return Math.max(Number.isFinite(declared) ? declared : 0, listed, Number.isFinite(fallbackCount) ? fallbackCount : 0);
};
/** IKN'den taze bir EKAP kaydı bulur (id token anlıktır, saklanamaz). */ /** IKN'den taze bir EKAP kaydı bulur (id token anlıktır, saklanamaz). */
export async function findByIkn(ikn) { export async function findByIkn(ikn) {
@@ -28,6 +34,10 @@ export async function findByIkn(ikn) {
/** İhale dokümanlarının EKAP görüntüleme/indirme adresini üretir. */ /** İhale dokümanlarının EKAP görüntüleme/indirme adresini üretir. */
export async function documentUrl(ikn) { export async function documentUrl(ikn) {
const t = await findByIkn(ikn); const t = await findByIkn(ikn);
// Arama yanıtındaki doküman sayısı gecikebilir; detay kaydı güncel
// doküman listesini taşıyorsa kullanıcıya onu göster.
let detail = null;
try { detail = await getIhaleDetay(t.id); } catch { /* yönlendirme yine üretilebilir */ }
const d = await ekapPost('/b_ihalearama/api/EkapDokumanYonlendirme/GetDokumanUrl', { const d = await ekapPost('/b_ihalearama/api/EkapDokumanYonlendirme/GetDokumanUrl', {
islemId: '1', islemId: '1',
ihaleId: t.id, ihaleId: t.id,
@@ -40,8 +50,8 @@ export async function documentUrl(ikn) {
ikn: t.ikn, ikn: t.ikn,
ihaleAdi: t.ihaleAdi, ihaleAdi: t.ihaleAdi,
idareAdi: t.idareAdi, idareAdi: t.idareAdi,
dokumanSayisi: t.dokumanSayisi ?? 0, dokumanSayisi: documentCount(detail, t.dokumanSayisi),
dokumanListe: t.dokumanListe || [], dokumanListe: detail?.dokumanListe || t.dokumanListe || [],
}; };
} }
@@ -82,6 +92,8 @@ export async function ilanMetni(ikn) {
idareAdi: d?.idareAdi || t.idareAdi, idareAdi: d?.idareAdi || t.idareAdi,
ilanSayisi: ilanlar.length, ilanSayisi: ilanlar.length,
okasSayisi: okas.length, okasSayisi: okas.length,
dokumanSayisi: documentCount(d, t.dokumanSayisi),
dokumanListe: d?.dokumanListe || t.dokumanListe || [],
...officialDate, ...officialDate,
metin: parcalar.join('\n'), metin: parcalar.join('\n'),
}; };
+5
View File
@@ -20,4 +20,9 @@ test('official five-tender evidence is complete and records the Aksaray date dis
assert.equal(aksaray.parsedAnnouncement.tarih, '16.09.2026'); assert.equal(aksaray.parsedAnnouncement.tarih, '16.09.2026');
assert.equal(aksaray.dateConsistency.announcementHtml, '09.09.2026 10:00'); assert.equal(aksaray.dateConsistency.announcementHtml, '09.09.2026 10:00');
assert.match(aksaray.parsedAnnouncement.sourceDateWarning, /güncel detay tarihi esas alındı/); assert.match(aksaray.parsedAnnouncement.sourceDateWarning, /güncel detay tarihi esas alındı/);
assert.equal(evidence.documentLinkChecks.cases.length, 5);
for (const check of evidence.documentLinkChecks.cases) {
assert.equal(check.hasUrl, true);
assert.ok(Number.isInteger(check.dokumanSayisi) && check.dokumanSayisi >= 0);
}
}); });