feat: DT detaylari tam cekiliyor — BransKodList=OKAS ile siniflandirma, ilan belgeleri, en yeni kayitlar oncelikli detay kuyrugu, butce 30->250

This commit is contained in:
2026-08-30 13:20:28 +03:00
parent d9ca8a5b52
commit f98568da8e
4 changed files with 71 additions and 9 deletions
+44 -6
View File
@@ -4,7 +4,7 @@
*/
import fs from 'node:fs';
import { sektorBul } from './siniflandir.mjs';
import { sektorKarar } from './siniflandir.mjs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { titleCaseTr } from './tr-text.mjs';
@@ -28,13 +28,37 @@ function parseDetail(detailJson) {
const dt = d.DogrudanTeminBilgileri || {};
const idare = d.IdareBilgileri || {};
const soz = d.SozlesmeBilgileri?.SozlesmeBilgisiList?.[0] || null;
const ilan = d.IlanBilgileri || {};
const duyuru = ilan.DogrudanTeminIlanBilgisiList?.[0] || null;
const sonuc = ilan.SonucIlanBilgisiList?.[0] || null;
const iptal = ilan.IptalIlanBilgisiList?.[0] || null;
return {
yasaMaddesi: dt.YasaKapsamiTeminMaddesi || null,
istisnaDayanagi: dt.IstisnaAliminDayanagi || null,
durum: dt.DtDurumu || null,
// BransKodList aslında OKAS (CPV) kodudur — idarenin kendi sınıflandırması.
bransKodlari: dt.BransKodList || [],
kismiTeklif: dt.KismiTeklif || null,
kisimSayisi: dt.KisimSayisi || null,
ilaninSekli: dt.IlaninSekli || null,
tarihSaat: dt.DtTarihSaati || null,
eIhale: Boolean(dt.EIhale),
duyuruYapilacak: Boolean(dt.DogrudanTeminDuyurusuYapilacakMi),
sozlesmeTasarisiVar: Boolean(dt.DogrudanTeminSozlesmeTasarisiVarMi),
iptalNedeni: dt.IptalNedeni || null,
iptalTarihi: dt.IptalTarihi || null,
idareTam: idare.Idare || null,
ustIdare: idare.UstIdare || null,
enUstIdare: idare.EnUstIdare || null,
ili: idare.Ili || null,
// İlan belgeleri — EncIlanId ile EKAP'ta görüntülenir
// EncIlanId → EKAP ilan görüntüleme adresi. Doğrulanmış tek yol
// EKAP arayüzü olduğundan bağlantıyı kullanıcının tarayıcısında açarız.
ilanlar: [
duyuru && { tip: 'Doğrudan Temin Duyurusu', tarih: duyuru.IlanTarihi, encId: duyuru.EncIlanId },
sonuc && { tip: 'Sonuç İlanı', tarih: sonuc.IlanTarihi, encId: sonuc.EncIlanId },
iptal && { tip: 'İptal İlanı', tarih: iptal.IlanTarihi, encId: iptal.EncIlanId },
].filter(Boolean),
kazananFirma: soz?.IstekliAdi || null,
sozlesmeBedeli: soz?.SozlesmeBedeli || null,
sozlesmeTarihi: soz?.SozlesmeTarihi || null,
@@ -71,18 +95,32 @@ function mapDtRow(row) {
sehir: row.ili && !row.ili.startsWith('Plaka') ? titleCaseTr(row.ili) : '',
bolge: '',
tarih: row.dt_tarihi || '',
saat: '',
saat: (det.tarihSaat || '').split(' ')[1] || '',
alimTuru: 'Doğrudan Temin',
usul: det.yasaMaddesi ? `Doğrudan Temin (4734 ${det.yasaMaddesi})` : 'Doğrudan Temin (4734 22/d)',
// Sektör ihale TÜRÜ değildir; başlık + kalem adlarından çıkarılır.
sektor: sektorBul(row.isin_adi || '', (det.bransKodlari || []).join(' '), row.turu || ''),
usul: det.yasaMaddesi
? `Doğrudan Temin (4734 ${det.yasaMaddesi})`
: det.istisnaDayanagi ? `Doğrudan Temin (istisna ${det.istisnaDayanagi})` : 'Doğrudan Temin',
// BransKodList = OKAS kodu → idarenin kendi sınıflandırması, başlıktan
// güvenilir. Kod yoksa iş adına düşülür.
sektor: sektorKarar(
(det.bransKodlari || []).map((k) => ({ kod: k })),
row.isin_adi || '',
),
brans: (det.bransKodlari || []).join(', ') || row.turu || 'Genel',
kurumTipi: classifyKurum(kurum),
eklenmeZamani: row.yayim_tarihi ? `Yayım: ${row.yayim_tarihi}` : '',
isYeni: false,
isLiveFeed: true,
aciliyetBadge: null,
items: [],
// OKAS kalemleri — arayüzde kod+ad gösterilebilsin
items: (det.bransKodlari || []).map((k, i) => ({
id: `okas-${i}`, kod: k, ad: `OKAS ${k}`, miktar: null, birim: null, birimFiyat: null,
})),
ilanBelgeleri: det.ilanlar || [],
ilaninSekli: det.ilaninSekli || null,
kismiTeklif: det.kismiTeklif || null,
eIhale: det.eIhale || false,
iptalNedeni: det.iptalNedeni || null,
aciklama: null,
yaklasikMaliyet: null,
teslimatSuresi: null,