fix: separate item price analysis by unit
This commit is contained in:
@@ -1324,6 +1324,12 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö
|
||||
- Analitik `parseDateTR`, JavaScript tarih yuvarlamasıyla 31 Şubat gibi imkânsız günleri geçerli tarihe dönüştürmüyordu; artık gün/ay/yıl bileşenlerini doğrulayıp geçersiz girdide `null` döndürüyor. Geçersiz tarihler yanlış hafta sonu veya kısa süre riskine dönüşmüyor.
|
||||
- 31.02.2026 reddi, artık yıl 29.02.2028 ve eğik çizgili geçerli tarih için regresyon testleri eklendi. 281 test ve build başarılı. Genel plan açık.
|
||||
|
||||
### 2026-09-06 — Fiyat analizinde birim ve miktar ayrımı
|
||||
|
||||
- D08 kapsamında `itemStats` aynı ürün adının kutu, adet veya başka birimlerdeki fiyatlarını artık tek medyanda birleştirmiyor. İstatistik anahtarı ürün + birim olarak ayrıldı.
|
||||
- Miktarı veya birimi kaynakta bilinmeyen kalemler fiyat analizine alınmıyor; böylece birim fiyat karşılaştırması doğrulanmamış kapsamla öneri üretmiyor.
|
||||
- Kutu/adet ve bilinmeyen miktar regresyonu eklendi. 282 test ve build başarılı. Gerçek pazar verisiyle fiyat karşılaştırması ve kur kaynağı kabulü hâlâ plan maddesi; genel plan açık.
|
||||
|
||||
### 2026-09-06 — Belge son kullanma tarihi doğrulaması
|
||||
|
||||
- Belge deposundaki son kullanma tarihi göstergesi artık yalnız geçerli ISO günlerini hesaplıyor. Bozuk veya yuvarlanabilir bir tarih sessizce gün hesabına girmiyor; kullanıcıya “Tarih doğrulanmalı” uyarısı gösteriliyor.
|
||||
|
||||
@@ -83,6 +83,8 @@ export function firmStats(tenders) {
|
||||
};
|
||||
}
|
||||
|
||||
import { quantityParts } from './bidValidation.js';
|
||||
|
||||
// --- Kalem bazlı fiyat analizi ---
|
||||
export function itemStats(tenders) {
|
||||
const map = new Map();
|
||||
@@ -92,8 +94,12 @@ export function itemStats(tenders) {
|
||||
const bf = parseTL(it.birimFiyat);
|
||||
if (bf == null) continue;
|
||||
itemCount++;
|
||||
const key = (it.ad || 'Diğer').trim().toLocaleUpperCase('tr-TR');
|
||||
const cur = map.get(key) || { ad: it.ad, birim: it.birim, count: 0, prices: [] };
|
||||
const quantity=quantityParts(it.miktar ?? it.quantity);
|
||||
const rawUnit=quantity.birim || it.birim || '';
|
||||
if (quantity.miktar == null || !String(rawUnit).trim()) { itemCount--; continue; }
|
||||
const unit=String(rawUnit).trim().toLocaleLowerCase('tr-TR');
|
||||
const key = `${(it.ad || 'Diğer').trim().toLocaleUpperCase('tr-TR')}||${unit}`;
|
||||
const cur = map.get(key) || { ad: it.ad, birim: unit, count: 0, prices: [] };
|
||||
cur.count++;
|
||||
cur.prices.push(bf);
|
||||
map.set(key, cur);
|
||||
|
||||
@@ -6,6 +6,16 @@ test('analytics rejects impossible Turkish calendar dates instead of rolling the
|
||||
assert.equal(parseDateTR('29.02.2028')?.getDate(),29);
|
||||
assert.equal(parseDateTR('30/04/2026')?.getMonth(),3);
|
||||
});
|
||||
test('item price analysis separates units and ignores unknown quantities',async()=>{
|
||||
const {itemStats}=await import('../src/services/analytics.js');
|
||||
const result=itemStats([{items:[
|
||||
{ad:'Test kiti',miktar:'2 kutu',birimFiyat:'10 TL'},
|
||||
{ad:'Test kiti',miktar:'3 adet',birimFiyat:'12 TL'},
|
||||
{ad:'Test kiti',miktar:'bilinmiyor',birimFiyat:'99 TL'},
|
||||
]}]);
|
||||
assert.equal(result.itemCount,2); assert.equal(result.uniqueItems,2);
|
||||
assert.deepEqual(result.items.map(x=>x.birim).sort(),['adet','kutu']);
|
||||
});
|
||||
import {hizliFiltreGecer} from '../src/services/ihaleTarih.js';
|
||||
import {applyTenderStates} from '../src/services/tenderState.js';
|
||||
test('review counter uses the same explicit state as reviewed and unread filters',()=>{
|
||||
|
||||
Reference in New Issue
Block a user