feat: konu bazlı bildirim + gerçek site tarama

1) Bildirim artık KONU odaklı (il değil)
   - Kullanıcı hangi konularda ihale alabildiğini seçer; varsayılan tüm Türkiye
   - İl/alım türü/favori kurum 'daha da daralt' altında isteğe bağlı
   - notify-store: konular kolonu + otomatik şema geçişi
   - notifier: konu başlıkları ihale başlığı/sektör/branş/kalemlerde aranır

2) Gerçek firma sitesi tarama (webScraperService mock'unun yerine)
   - server/site-scan.mjs: siteyi GERÇEKTEN çeker, ana sayfa + ürün/hizmet/
     hakkımızda iç sayfalarını tarar, HTML'i metne çevirir, AI ile firmanın
     tedarik edebildiği ihale konularını çıkarır ('uydurma' yasaklı prompt)
   - /api/company/scan (auth'lu)
   - ai.mjs: systemOverride desteği (farklı görevler için ayrı sistem promptu)
   - Arayüz: 'Sitenizi tarayıp konuları otomatik önerelim' → tıklayarak ekleme

Not: eski webScraperService.js sabit anahtar-kelime sözlüğüydü; domain adında
'tanriverdi' geçince tıbbi ürün listesi uyduruyordu.
This commit is contained in:
2026-08-29 10:19:44 +03:00
parent b44b45c67e
commit f73c7bd6cb
6 changed files with 350 additions and 114 deletions
+6
View File
@@ -23,6 +23,11 @@ export function eslesiyorMu(t, a) {
const alan = norm(`${t.baslik || ''} ${t.kurum || ''} ${(t.items || []).map((i) => i.ad).join(' ')}`);
if (!alan.includes(q)) return false;
}
// Konu başlıkları: herhangi biri ihale metninde geçiyorsa eşleşir
if (a.konular?.length) {
const alan = norm(`${t.baslik || ''} ${t.sektor || ''} ${t.brans || ''} ${(t.items || []).map((i) => i.ad).join(' ')}`);
if (!a.konular.some((k) => alan.includes(norm(k)))) return false;
}
if (a.kurumlar?.length) {
const kurum = norm(t.kurum);
if (!a.kurumlar.some((k) => norm(k) === kurum)) return false;
@@ -76,6 +81,7 @@ export async function bildirimleriIsle(tenderGetir, { zorla = false } = {}) {
a.sektor && `Sektör: ${a.sektor}`,
a.alimTuru && `Tür: ${a.alimTuru}`,
a.anahtar && `Anahtar: ${a.anahtar}`,
a.konular?.length && `Konular: ${a.konular.slice(0, 4).join(', ')}${a.konular.length > 4 ? '…' : ''}`,
a.kurumlar?.length && `${a.kurumlar.length} favori kurum`,
].filter(Boolean).join(' · ') || 'Tüm ihaleler';