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:
+44
-6
@@ -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,
|
||||
|
||||
@@ -36,7 +36,7 @@ const argVal = (name, def) => {
|
||||
return i >= 0 && args[i + 1] ? Number(args[i + 1]) : def;
|
||||
};
|
||||
const MAX_PAGES = argVal('--pages', 10);
|
||||
const MAX_DETAILS = argVal('--details', 40);
|
||||
const MAX_DETAILS = argVal('--details', 250);
|
||||
const DELAY_BASE_MS = 2000;
|
||||
const DELAY_JITTER_MS = 1500;
|
||||
|
||||
@@ -265,8 +265,12 @@ async function run() {
|
||||
// 2) Eksik detaylar
|
||||
const pending = db
|
||||
.prepare(
|
||||
// EN YENİ kayıtlar önce: arayüz en yeni 5000'i gösteriyor; varsayılan
|
||||
// (rowid) sırada en eskiler çekildiği için gösterilen hiçbir kayda
|
||||
// detay ulaşmıyordu.
|
||||
`SELECT dogrudan_temin_id, idare_id FROM dt_tenders
|
||||
WHERE detail_json IS NULL AND idare_id != '' LIMIT ?`,
|
||||
WHERE detail_json IS NULL AND idare_id != ''
|
||||
ORDER BY rowid DESC LIMIT ?`,
|
||||
)
|
||||
.all(MAX_DETAILS);
|
||||
console.log(`[dt-worker] ${pending.length} detay çekilecek`);
|
||||
|
||||
@@ -101,7 +101,9 @@ function dtTara() {
|
||||
dtCalisiyor = true;
|
||||
dtSonTur = { baslangic: new Date().toISOString() };
|
||||
const pages = process.env.DT_PAGES || '5';
|
||||
const details = process.env.DT_DETAILS || '30';
|
||||
// 30 detay/4 saat ile 10 bin kayıt 55 günde dolar; sektör sınıflandırması
|
||||
// detaya bağlı olduğu için bütçe yükseltildi.
|
||||
const details = process.env.DT_DETAILS || '250';
|
||||
console.log(`[scheduler] doğrudan temin taraması başlıyor (${pages} sayfa, ${details} detay)`);
|
||||
|
||||
const p = spawn(process.execPath, [path.join(__dirname, 'dt-worker.mjs'), '--pages', pages, '--details', details], {
|
||||
|
||||
@@ -118,8 +118,26 @@ export function ilanKonusu(metin) {
|
||||
const OKAS_GRUP = {
|
||||
// 39 — mobilya / ev aletleri / temizlik ürünleri aynı bölümde
|
||||
'3971': 'Isıtma & İklimlendirme', // elektrikli ev aletleri (buzdolabı, klima)
|
||||
'3922': 'Temizlik & Hijyen', // süpürge, fırça, temizlik gereçleri
|
||||
'3953': 'Temizlik & Hijyen', // paspas, yer örtüsü
|
||||
'3983': 'Temizlik & Hijyen', // temizlik ürünleri
|
||||
'3984': 'Temizlik & Hijyen',
|
||||
// 33 — tıbbi bölümde hijyenik kâğıt da var
|
||||
'3376': 'Temizlik & Hijyen', // tuvalet kâğıdı, kâğıt havlu
|
||||
'3377': 'Temizlik & Hijyen',
|
||||
// 50 — bakım/onarım hizmetleri: taşıt onarımı ayrılır
|
||||
'5011': 'Otomotiv & İş Makinesi',
|
||||
'5012': 'Otomotiv & İş Makinesi',
|
||||
'5013': 'Otomotiv & İş Makinesi',
|
||||
'5014': 'Otomotiv & İş Makinesi',
|
||||
// 03 — tarımsal ürünlerin yenilebilir olanları gıdadır
|
||||
'0311': 'Gıda & Catering',
|
||||
'0313': 'Gıda & Catering',
|
||||
'0314': 'Gıda & Catering',
|
||||
'0321': 'Gıda & Catering',
|
||||
'0322': 'Gıda & Catering',
|
||||
'0331': 'Gıda & Catering',
|
||||
'0332': 'Gıda & Catering',
|
||||
// 79 — iş hizmetleri: güvenlik, matbaa, reklam, danışmanlık, personel
|
||||
'7971': 'Güvenlik Sistemleri',
|
||||
'7972': 'Güvenlik Sistemleri',
|
||||
|
||||
Reference in New Issue
Block a user