normalize tender result status in dedupe

This commit is contained in:
2026-09-06 19:25:08 +03:00
parent cc3c3ad73d
commit bd5c122522
3 changed files with 14 additions and 1 deletions
+6
View File
@@ -2260,3 +2260,9 @@ Doğrulama: browserTimezone `America/New_York`, mobil viewport 390 px ve yatay t
Canlı drift probe’u artık API yanıt gövdesini de doğruluyor: `/api/health` için `ok:true`, `/api/ready` için `success:true` ve JSON içerik türü aranıyor. Böylece HTTP 200 dönen SPA/ara hata sayfaları sağlıklı servis kabul edilmiyor.
Güncel canlı sonuçta health `ok:true` olsa da readiness `404` ve güvenlik başlıkları eksik olduğu için probe başarısız kaldı; kanıt `qa-live-runtime.json` içinde.
### 2026-09-06 · D04 sonuç durumu normalizasyonu
Kaynaklar `Sonuçlandı` durumunu boşluk veya büyük/küçük harf farkıyla döndürdüğünde tekilleştirme artık aynı award anahtarını kullanıyor. Lot numarası hâlâ kimliğin parçası; farklı kısımlar birbirine karışmıyor ve aynı lotun farklı kaynak kayıtları birleşiyor.
Doğrulama: yeni regresyonla otomatik test sayısı 295/295’e yükseldi; üretim derlemesi başarılı.
+1 -1
View File
@@ -2,7 +2,7 @@ const norm = v => String(v || '').trim().replace(/\s+/g,' ').toLocaleLowerCase('
export function tenderIdentity(t) {
const ikn = String(t.ikn || '').replace(/\s/g,'');
// Awards from different lots must never be collapsed into one contract.
if (t.durum === 'Sonuçlandı') return `award:${ikn}:${t.kisim ?? t.id}:${norm(t.kazananFirma)}`;
if (norm(t.durum) === 'sonuçlandı') return `award:${ikn}:${t.kisim ?? t.id}:${norm(t.kazananFirma)}`;
if (/^\d{2}DT\d+$/i.test(ikn)) return `dt:${ikn.toUpperCase()}:${norm(t.kurum)}`;
// Corrections/cancellations remain separate events until their source linkage is verified.
if (/düzeltme|zeyilname|iptal/i.test(t.baslik || '')) return `event:${t.id}`;
+7
View File
@@ -11,6 +11,13 @@ test('distinct contract lots and corrections remain separate',()=>{
assert.equal(uniqueTenders([t,t,{...t,id:'b',kisim:'2'}]).length,2);
assert.equal(uniqueTenders([{ikn:'2026/123',id:'1'},{ikn:'2026/123',id:'2',baslik:'Düzeltme ilanı'}]).length,2);
});
test('result status whitespace is normalized without collapsing distinct lots',()=>{
const first={ikn:'2026/456',durum:' Sonuçlandı ',kisim:'1',id:'a',kazananFirma:'Firma'};
const same={...first,id:'b'};
const other={...first,id:'c',kisim:'2'};
const out=uniqueTenders([first,same,other]);
assert.equal(out.length,2);assert.deepEqual(out[0].sourceIds,['a','b']);
});
test('malformed source rows do not crash pool deduplication',()=>{
const out=uniqueTenders([null,42,{},[],{ikn:'2026/123',baslik:'Eksik kimlik'}]);
assert.deepEqual(out,[]);