# ULTRAAPP Lead Radar

Kocaeli pilot bölgesi için firma keşif, dijital eksik analizi ve saha satış portalı.

## Amaç

[ULTRAAPP Software](https://www.ultraapp.com.tr) (İzmit/Kocaeli) için müşteri adayı bulmak.
Çıktı bir firma listesi değil, **"yarın kimi arayacağım / kimi ziyaret edeceğim"** cevabıdır.

### Hizmet kataloğu (fırsat eşleştirmesinin hedefi)

| Anahtar | Hizmet | Fiyat | Tip |
|---|---|---|---|
| `web` | Kurumsal Web Sitesi | 20.000₺ | tek seferlik |
| `eticaret` | E-Ticaret Sitesi | 75.000₺ | tek seferlik |
| `mobil` | Mobil Uygulama | teklife göre | tek seferlik |
| `seo` | SEO Hizmeti | 10.000₺/ay | **tekrarlayan** |
| `sosyal` | Sosyal Medya Yönetimi | 50.000₺/ay | **tekrarlayan** |
| `crm` | CRM / ERP Projesi | teklife göre | tek seferlik |

## Kısıtlar (proje kararları)

1. **Veri maliyeti sıfır.** Ücretli API veya abonelik yok. Kaynaklar: OpenStreetMap,
   Google PageSpeed Insights (ücretsiz kota), oda/OSB üye listeleri, kendi kazıyıcımız.
2. **İletişim kanalı: telefon + yüz yüze ziyaret.** Toplu e-posta/SMS yok.
   Bu hem KVKK/İYS açısından en güvenli yol, hem firmanın Kocaeli'de fiziksel
   olarak bulunmasının avantajını kullanır. Sistem bu yüzden bir "e-posta gönderme
   aracı" değil, bir **saha satış aracı** olarak tasarlandı.
3. **Pilot bölge: Kocaeli.** Önce İzmit + Gebze.

## Boru hattı

```
KEŞİF  →  ZENGİNLEŞTİRME  →  DENETİM  →  SKORLAMA  →  PANO  →  SAHA  →  CRM
```

| Aşama | Ne yapar | Durum |
|---|---|---|
| Keşif | OSM'den sektör × bölge taraması | ✅ çalışıyor |
| İlçe tespiti | Gerçek idari sınırlarla nokta-poligon | ✅ çalışıyor |
| Zenginleştirme | Site + sosyal medya keşfi | ✅ çalışıyor |
| Denetim | SSL, mobil, hız, teknoloji parmak izi | ✅ çalışıyor |
| Skorlama | Dijital olgunluk + fırsat skoru + hizmet eşleştirme | ✅ çalışıyor |
| Görüşme kartı | Açılış cümlesi, acı noktaları, itiraz cevapları | ✅ çalışıyor |
| Pano | Filament arayüzü, filtreler, firma dosyası | ✅ çalışıyor |
| Liste içe aktarma | Oda/OSB/Ticaret Sicil listelerini yapıştırıp alma | ✅ çalışıyor |
| Saha | Günlük rota planlama | ⬜ |
| CRM | Görüşme kaydı, takip, dönüşüm | ⬜ |

## Skorlama modeli

```
Fırsat Skoru = İhtiyaç Şiddeti  × 0.40    ← dijital olgunluk ne kadar düşükse o kadar yüksek
             + Ödeme Gücü       × 0.30    ← ölçek, sektör önceliği, yorum sayısı
             + Ulaşılabilirlik  × 0.15    ← telefon var mı, ofise uzaklık
             + Aciliyet         × 0.15    ← yeni kurulmuş, büyüyor
             − Eleme cezaları              ← zincir marka, ajansı var, mikro işletme
```

`app/Enums/DigitalMaturity::need()` ve `app/Enums/Scale::weight()` bu formülün
ham girdilerini üretir.

## Veri kaynakları

Hepsi `data_sources` tablosunda kayıtlı; her firmanın `source` + `source_url`
alanı KVKK açısından "bu veriyi nereden aldık" sorusunu cevaplar.

| Anahtar | Kaynak | Lisans / kota |
|---|---|---|
| `osm` | OpenStreetMap Overpass API | ODbL — ticari kullanım serbest, atıf zorunlu |
| `psi` | Google PageSpeed Insights | ücretsiz, 25.000 istek/gün |
| `website_crawl` | Firmanın kendi sitesi | halka açık, robots.txt'e uyulur |
| `search_discovery` | Arama motoru ile site/sosyal keşfi | halka açık sonuçlar |
| `kosano` / `koto` / `osb` | Oda ve OSB üye listeleri | halka açık rehber |
| `ticaret_sicil` | Ticaret Sicil Gazetesi | resmî ilan — **en sıcak lead kaynağı** |
| `tobb_sanayi` | TOBB Sanayi Veritabanı | ücretsiz üyelik, ~70.000 üretici |
| `bulurum` | Firma rehberi | halka açık işletme rehberi, schema.org mikro veri |

### Kapsama: OSM tek başına yetmiyor

Ölçüldü: OSM Kocaeli genelinde **34 diş kliniği** biliyor, gerçekte birkaç yüz var.

Çözüm **firma rehberi taraması** (`kesif:rehber`). Aynı sektörde tek taramada
**274 kayıt / 167 yeni firma** getirdi — 5-10 kat kapsama farkı. Rehber sayfaları
schema.org `LocalBusiness` mikro verisi taşıyor: ad, koordinat, ilçe, adres,
kategori ve telefon yapısal olarak işaretlenmiş durumda.

İkisi birbirini tamamlıyor:

| | OSM | Rehber |
|---|---|---|
| Kapsama | Zayıf (küçük işletme) | Geniş |
| Telefon | Nadir | Çoğunlukla var |
| Koordinat | Her zaman | Çoğunlukla |
| Sanayi/fabrika | İyi | Orta |

Aynı firma iki kaynaktan da gelirse **ilçe + sadeleştirilmiş ad** ile tekilleştirilir;
rehber verisi mevcut alanları ezmez, yalnızca boşları doldurur.

## Komutlar

### Tek komut

```bash
php artisan sistem:calistir --kesif --rehber      # her şeyi baştan sona
php artisan sistem:calistir --butce=100           # günlük çalıştırma
php artisan sistem:calistir --tahmin-only         # hiç kota harcamaz
```

Sırayla çalıştırdığı adımlar: keşif → ön skorlama → zenginleştirme (bütçeli)
→ son skorlama → görüşme kartları. Ön skorlama önce yapılır ki sınırlı arama
kotası doğru firmalara harcansın.

### Ayrı ayrı

```bash
# Kocaeli ilçe sınırlarını OSM'den çek (bir kez; yeni kurulumda ilk çalıştırılacak)
php artisan ilce:sinirlari
php artisan ilce:sinirlari --yeniden-ata   # mevcut firmaların ilçesini de düzeltir

# Firma keşfi
php artisan kesif:osm                          # tüm hedef sektörler, tüm Kocaeli
php artisan kesif:osm --sektor=dis_klinigi     # tek sektör
php artisan kesif:osm --oncelik=85             # sadece yüksek öncelikli sektörler
php artisan kesif:osm --ilce=gebze             # tek ilçe
php artisan kesif:osm --bekle=5                # Overpass'e daha nazik davran

# Firma rehberi taraması — asıl kapsama buradan gelir
php artisan kesif:rehber                       # tüm hedef sektörler
php artisan kesif:rehber --sektor=oto_galeri --sayfa=30
php artisan kesif:rehber --oncelik=85          # sadece yüksek öncelikli sektörler

# Zenginleştirme: site + sosyal medya bul, siteyi denetle
php artisan zenginlestir --limit=200 --arama-butcesi=50
php artisan zenginlestir --tahmin-only          # kota harcamaz, sadece alan adı tahmini
php artisan zenginlestir --min-skor=60          # sadece değerli firmalar
php artisan zenginlestir --yeniden

# Skorlama ve hizmet eşleştirme
php artisan skorla                              # yeni analiz edilenler
php artisan skorla --hepsi                      # ağırlıklar değiştiyse tümünü yeniden

# Saha görüşme kartları
php artisan gorusme-karti                       # kartı olmayanlar
php artisan gorusme-karti --hepsi
php artisan gorusme-karti --firma=12
```

Tipik akış:
```bash
php artisan kesif:osm --oncelik=85 && php artisan zenginlestir --limit=50   && php artisan skorla && php artisan gorusme-karti
```

## Panel

`http://ultraappfirmabulma.test/admin` · giriş: `business@ultraapp.com.tr`

| Sayfa | İçerik |
|---|---|
| Gösterge paneli | Sıcak lead sayısı, bugün gidilebilecekler, açık fırsat değeri, doğrulama bekleyenler + "Bugün aranacaklar" listesi |
| Lead Panosu | Fırsat skoruna göre sıralı çalışma listesi. 11 filtre, satır içi ara/WhatsApp/harita/doğrula işlemleri |
| Firma dosyası | Görüşme kartı, skor dökümü, site denetimi, sosyal medya, KVKK kaynak izi |
| Liste İçe Aktar | Oda/OSB/Ticaret Sicil listelerini yapıştırıp alma |

## Yeni firma kaynakları — neden içe aktarma

En değerli kaynaklar API sunmuyor:

- **Ticaret Sicil Gazetesi** üyelik + CAPTCHA istiyor. Otomatik kazımak erişim
  kontrolünü aşmak olurdu; yapılmadı.
- **KOSANO / KOTO / OSB / TOBB** listeleri de üyelik veya elle gezinme gerektiriyor.

Çözüm: kullanıcı kendi hesabıyla eriştiği listeyi **Liste İçe Aktar** sayfasına
yapıştırır. Sistem sütunları Türkçe/İngilizce başlık takma adlarıyla tanır,
ilçeyi eşleştirir, mesafeyi hesaplar, aynı firmayı iki kez eklemez ve mevcut
veriyi ezmez (yalnızca boş alanları doldurur).

Otomatik "yeni firma" sinyali ayrıca var: OSM taramalarında **yeni beliren**
kayıtlar `first_seen_at` ile işaretlenir, panoda "Son 30 günde bulunanlar"
filtresiyle görünür.

## Arama motoru kararı (önemli)

Web sitesi keşfi için arama motoru **kazınmıyor**. Üçü de denendi ve ölçüldü:

| Denenen | Sonuç |
|---|---|
| DuckDuckGo (lite + html) | HTTP 202 — yumuşak engelleme, hiç sonuç yok |
| Bing | HTTP 200 ama **alakasız sonuçlar** — İzmit sorgusuna Silivri sonuçları |
| Mojeek / SearXNG / Startpage | Boş veya kullanılamaz |

Bing'in davranışı en tehlikelisi: sessizce yanlış veri üretiyor. Bu yüzden
sadece **resmî API** destekleniyor (`config/leadradar.php`):

- `LEAD_SEARCH_DRIVER=none` (varsayılan) — yalnızca alan adı tahmini çalışır
- `LEAD_SEARCH_DRIVER=tavily` — **önerilen.** Aylık 1.000 sorgu ücretsiz,
  kredi kartı istemiyor, e-posta ile kayıt yeterli. `TAVILY_API_KEY=tvly-...`
- `LEAD_SEARCH_DRIVER=google_cse` — **yeni kurulumda kullanılamaz.**
  Google Custom Search JSON API **20 Ocak 2026'da yeni müşterilere kapatıldı**;
  mevcut müşteriler de 1 Ocak 2027'ye kadar taşınmak zorunda. Sürücü yalnızca
  elinde eski anahtar olanlar için duruyor.

Brave Search API de Şubat 2026'da ücretsiz katmanını kaldırıp kart zorunluluğu
getirdi. Kredi kartı istemeyen, tekrar eden ücretsiz kotası olan sağlayıcı
şu an Tavily.

Anahtarı ekledikten sonra doğrulayın:

```bash
php artisan arama:test
php artisan arama:test "Firma Adı İzmit"
```

Arama kapalıyken ve alan adı tahmini tutmazsa firma **"sitesi yok" değil,
"bilinmiyor"** olarak işaretlenir. Yanlış veri üretmemek için kasıtlı.
Panoda tek tıkla elle doğrulanacak.

## Veri modeli

| Tablo | Rol |
|---|---|
| `companies` | Merkez tablo. Kimlik, konum, iletişim, ölçek, skorlar, satış durumu |
| `sectors` | İki seviyeli TR taksonomi. OSM etiketleri + hedef hizmetler + eleme kuralları |
| `districts` | Kocaeli ilçeleri + gerçek idari sınır poligonu |
| `services` | ULTRAAPP hizmet kataloğu |
| `website_audits` | Site denetimi: SSL, hız, mobil, teknoloji, bulgular, kanıtlar |
| `company_socials` | Sosyal medya hesapları + aktiflik durumu |
| `opportunities` | Firma × hizmet eşleşmesi + skor + tahmini değer |
| `sales_briefs` | Görüşme kartı: açılış cümlesi, acı noktaları, itiraz cevapları |
| `interactions` | CRM: her arama/ziyaret/not |
| `visit_routes` + `visit_route_stops` | Günlük saha rotası |
| `scan_jobs` + `data_sources` | Tarama geçmişi ve kaynak kaydı (KVKK izlenebilirliği) |
| `blacklist_entries` | "Bir daha aramayın" listesi |

## Kurulum notları

- PHP 8.3.30 (Laragon). `zip` eklentisi projede açıldı (`php.ini`).
- MySQL 8.4.3, veritabanı: `ultraapp_lead`
- Laravel 13 + Filament 5
- Kuyruk sürücüsü: `database` — uzun taramalar arka planda çalışacak

## Sınırlar ve dikkat edilecekler

- **Google Maps kazınmıyor.** Kullanım şartlarına aykırı ve IP engeli riski var.
  Omurga OSM + resmî TR kaynakları üzerine kuruldu; Google elle doğrulama için
  açık bırakıldı.
- **Arama kutusu il sınırından geniştir.** Kocaeli dışına taşan kayıtlar
  (Sakarya, İstanbul) `DistrictLocator` tarafından eleniyor — en yakın ilçeye
  yapıştırılmaları saha rotasını bozuyordu.
- **İYS/KVKK:** Toplu ticari elektronik ileti göndermek İYS kaydı gerektirir
  (2026 cezaları: kişi başı ~14.300₺, toplu gönderimde 143.000₺'ye kadar).
  Sistem bu yüzden telefon/yüz yüze temas üzerine kurgulandı.
- **Filament closure parametreleri isme göre enjekte edilir.** `fn (Builder $q)`
  yazınca `$q` null gelir; parametre adı `$query`, `$record`, `$state` olmalı.
- **`User` modeli `FilamentUser` uygulamalı.** Aksi halde Filament `local`
  dışındaki her ortamda 403 döner — yayına alındığında panel kapanırdı.
- **Site eşleştirmede kelime sınırı şart.** Alt dizi araması alakasız siteleri
  firmanın sitesi sanıyordu: "Beyaz Diş Sağlığı Merkezi" → beyaz.net, çünkü
  "merkezi" o sitedeki "veri merkezi" ifadesinde geçiyordu. `WebsiteFinder`
  artık kelime olarak eşleştiriyor ve tek kelimelik isimlerde konum
  doğrulaması istiyor.
