# Telegram Saatlik Arama Raporu — Format Taslağı

> Bu dosya cron görevinin veri çekme işleminden **sonra** Telegram'a göndereceği mesajın formatını tanımlar.  
> Aşağıdaki **Örnek mesaj** bölümü, gruba gönderilecek nihai metindir.

---

## Tetikleme

| Özellik | Değer |
|---|---|
| Cron dosyası | `cron/arama_kayitlari.php` |
| Ne zaman | CDR verisi çekilip veritabanına kaydedildikten **hemen sonra** |
| Zaman aralığı | Son **1 saat** (`arama_tarihi >= NOW() - INTERVAL 1 HOUR`) |
| Saat dilimi | `Europe/Istanbul` |
| Hedef | `telegram_ayar` tablosundaki aktif bot + chat_id |

---

## Veri kaynakları

| Tablo | Kullanım |
|---|---|
| `arama_kayitlari` | Çağrı kayıtları (`kaynak`, `durum`, `arama_tarihi`, `sure_saniye`) |
| `sip_personel` | SIP kodu → personel adı eşleştirmesi |
| `telegram_ayar` | Bot token ve grup chat_id |

---

## Durum kodları (veritabanı → mesaj)

Panelden gelen `durum` değerleri veritabanında İngilizce saklanır; Telegram mesajında Türkçe gösterilir:

| Veritabanı (`durum`) | Mesajda gösterim |
|---|---|
| `ANSWERED` | Cevaplanan |
| `NO ANSWER` | Cevapsız |
| `BUSY` | Meşgul |
| *(diğer)* | Olduğu gibi veya otomatik Türkçeleştirilir |

---

## Mesaj şablonu

Aşağıdaki blok Telegram'a gönderilecek metnin taslağıdır.  
`{...}` ile işaretli alanlar çalışma anında doldurulur.

```
📊 Saatlik Arama Raporu
🕐 {baslangic_saati} — {bitis_saati}
📅 {tarih}

📞 Toplam Çağrı: {toplam_cagri}
{durum_satirlari}

👥 Personel Bazlı
{personel_satirlari}
```

### `{durum_satirlari}` formatı

Her durum için bir satır (Türkçe etiket):

```
• Cevaplanan: {adet}
• Cevapsız: {adet}
• Meşgul: {adet}
```

> **Not:** Sadece adet > 0 olan durumlar mı gösterilsin, yoksa hepsi mi?  
> → Şu anki taslak: **sadece adet > 0 olanlar**

### `{personel_satirlari}` formatı

Her aktif personel için ayrı blok (`sip_personel` sırasına göre):

```
▫️ {personel_adi} ({sip_kodu})
Toplam: {personel_toplam}
• Cevaplanan: {adet}
• Cevapsız: {adet}
• Meşgul: {adet}
• Görüşme süresi: {sure_metni_kisa}
• Max bekleme: {max_bekleme_metni_kisa}
```

#### Toplam görüşme süresi kuralları

| Kural | Değer |
|---|---|
| Hangi çağrılar | Yalnızca `durum = ANSWERED` (Cevaplanan) |
| Kaynak alan | `sure_saniye` toplamı |
| Zaman aralığı | Son 1 saat |
| Format | `{dakika} dk {saniye} sn` veya `{saat} sa {dakika} dk {saniye} sn` |
| Cevaplanan yoksa | `0 sn` |

Örnek süre metinleri:
- `46 sn`
- `1 dk 41 sn`
- `1 sa 5 dk 0 sn`

#### Maksimum bekleme süresi kuralları

Personelin son 1 saatteki **tüm çağrıları** (`durum` fark etmeksizin) `arama_tarihi` sırasına göre dizilir.  
Ardışık iki çağrı arasındaki boşluk = bir önceki çağrının **bitiş zamanı** ile sonraki çağrının **başlangıç zamanı** arasındaki fark.

```
bitis_zamani     = arama_tarihi + sure_saniye
bekleme_suresi   = sonraki.arama_tarihi - bitis_zamani
max_bekleme      = MAX(bekleme_suresi)  ← personel için en uzun işlemsiz bekleme
```

| Kural | Değer |
|---|---|
| Hangi çağrılar | Son 1 saatteki **tüm çağrılar** |
| Sıralama | `arama_tarihi` artan |
| Bitiş zamanı | `arama_tarihi + COALESCE(sure_saniye, 0)` saniye |
| Hesaplama | Ardışık çağrı çiftleri arasındaki en büyük boşluk |
| Format | `{dakika} dk {saniye} sn` (mobil kısa format) |
| Tek çağrı varsa | `0 sn` (karşılaştırılacak çift yok) |

Örnek:
- Çağrı A bitiş: `15:10:34` → Çağrı B başlangıç: `15:14:06` → bekleme = **3 dakika 32 saniye**
- Personelin tüm çiftleri arasında en büyük olan değer rapora yazılır.

> **Not:** Çağrısı olmayan personel listede görünsün mü?  
> → Şu anki taslak: **hayır, sadece son 1 saatte çağrısı olanlar**

> **Not:** `sip_personel` tablosunda kaydı olmayan SIP kodları?  
> → Şu anki taslak: SIP kodu gösterilir → `Bilinmeyen (9003)`

---

## Örnek mesaj (gönderilecek metin — HTML, mobil uyumlu)

```
<b>📊 Saatlik Arama Raporu</b>
🕐 14:56 — 15:56
📅 04.07.2026

<b>📞 Toplam Çağrı:</b> 87
• Cevaplanan: 12
• Cevapsız: 68
• Meşgul: 7

<b>👥 Personel Bazlı</b>

<b>▫️ Melisa (9001)</b>
Toplam: 15
• Cevaplanan: 2
• Cevapsız: 12
• Meşgul: 1
• Görüşme süresi: 46 sn
• Max bekleme: 3 dk 15 sn

<b>▫️ Ayşe (9002)</b>
Toplam: 18
• Cevaplanan: 3
• Cevapsız: 14
• Meşgul: 1
• Görüşme süresi: 1 dk 41 sn
• Max bekleme: 4 dk 52 sn
```

> **Mobil not:** Uzun `━━━━━━━━` ayırıcıları ve sabit genişlik hizalama kaldırıldı. Süreler kısa formatta (`1 dk 41 sn`). Telegram `parse_mode: HTML` kullanılır.

---

## Sorgu mantığı (referans)

### Toplam + durum dağılımı

```sql
SELECT durum, COUNT(*) AS adet
FROM arama_kayitlari
WHERE arama_tarihi >= NOW() - INTERVAL 1 HOUR
GROUP BY durum
ORDER BY adet DESC;
```

### Personel bazlı

```sql
SELECT
    COALESCE(sp.personel_adi, CONCAT('Bilinmeyen (', ak.kaynak, ')')) AS personel,
    ak.kaynak AS sip_kodu,
    ak.durum,
    COUNT(*) AS adet
FROM arama_kayitlari ak
LEFT JOIN sip_personel sp ON sp.sip_kodu = ak.kaynak AND sp.aktif = 1
WHERE ak.arama_tarihi >= NOW() - INTERVAL 1 HOUR
GROUP BY ak.kaynak, sp.personel_adi, ak.durum
ORDER BY personel, ak.durum;
```

### Personel görüşme süresi (yalnızca cevaplanan)

```sql
SELECT
    COALESCE(sp.personel_adi, CONCAT('Bilinmeyen (', ak.kaynak, ')')) AS personel,
    ak.kaynak AS sip_kodu,
    COALESCE(SUM(ak.sure_saniye), 0) AS toplam_saniye
FROM arama_kayitlari ak
LEFT JOIN sip_personel sp ON sp.sip_kodu = ak.kaynak AND sp.aktif = 1
WHERE ak.arama_tarihi >= NOW() - INTERVAL 1 HOUR
  AND ak.durum = 'ANSWERED'
GROUP BY ak.kaynak, sp.personel_adi
ORDER BY personel;
```

> Kod tarafında `toplam_saniye` → `{saat} saat, {dakika} dakika {saniye} saniye` formatına çevrilir.

### Personel maksimum bekleme süresi

Bu hesap SQL window function veya PHP tarafında ardışık kayıt karşılaştırması ile yapılır.

**PHP mantığı (özet):**

```php
// Personelin son 1 saatteki çağrıları arama_tarihi ASC
$cagrilar = [...]; // arama_tarihi, sure_saniye

$maxBekleme = 0;
for ($i = 0; $i < count($cagrilar) - 1; $i++) {
    $bitis = strtotime($cagrilar[$i]['arama_tarihi']) + (int)($cagrilar[$i]['sure_saniye'] ?? 0);
    $sonrakiBaslangic = strtotime($cagrilar[$i + 1]['arama_tarihi']);
    $bekleme = $sonrakiBaslangic - $bitis;
    if ($bekleme > $maxBekleme) {
        $maxBekleme = $bekleme;
    }
}
// $maxBekleme saniye → "0 saat, X dakika Y saniye"
```

**Veri çekme sorgusu:**

```sql
SELECT kaynak, arama_tarihi, COALESCE(sure_saniye, 0) AS sure_saniye
FROM arama_kayitlari
WHERE arama_tarihi >= NOW() - INTERVAL 1 HOUR
ORDER BY kaynak, arama_tarihi ASC;
```

---

## Düzenlenebilir alanlar (kontrol listesi)

Aşağıdaki maddeleri ihtiyacınıza göre değiştirin:

- [ ] Mesaj başlığı / emoji kullanımı
- [ ] Tarih formatı (`04.07.2026` vs `2026-07-04`)
- [ ] Durum etiketleri (Cevaplanan, Cevapsız, Meşgul)
- [ ] Personel sıralama (ada göre / toplam çağrıya göre / SIP koduna göre)
- [ ] Toplam görüşme süresi etiketi ve formatı
- [ ] Maksimum bekleme süresi etiketi ve formatı
- [ ] Çağrısı olmayan personelin gösterimi
- [ ] Sadece adet > 0 durum satırları mı, hepsi mi
- [ ] Son 1 saat yerine farklı aralık (30 dk, 2 saat vb.)
- [ ] Veri yoksa gönderilecek mesaj: `"Son 1 saatte çağrı kaydı bulunamadı."`

---

## Veri yok senaryosu

Son 1 saatte kayıt yoksa gönderilecek alternatif mesaj:

```
📊 Saatlik Arama Raporu
🕐 {baslangic_saati} — {bitis_saati}
📅 {tarih}

Son 1 saatte çağrı kaydı bulunamadı.
```

---

## Telegram API

```
POST https://api.telegram.org/bot{BOT_TOKEN}/sendMessage
Content-Type: application/json

{
  "chat_id": "{CHAT_ID}",
  "text": "{mesaj_metni}",
  "parse_mode": "HTML"
}
```

> **Not:** Mesajlar `parse_mode: HTML` ile gönderilir (`<b>` başlıklar). Mobil ekranlarda taşmayı önlemek için uzun ayırıcı çizgiler kullanılmaz.
