> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mmmytics.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Per-Brand Benchmark Override

> Phase 24 — Sektör default'ları yerine marka-spesifik KPI eşik değerleri tanımlayın. CEO/CMO rolü, channel × metric matrisi, deep merge stratejisi.

# Per-Brand Benchmark Override

`v0.7.57+58+60` (Phase 24) ile gelen **per-brand benchmark override** özelliği, sektör default eşik değerleri yerine markaya özel KPI sınırlarını tanımlamanıza olanak tanır. `CEO`/`CMO` rolündeki kullanıcılar **Settings → Benchmark Override** sekmesinden channel × metric matrisinde override girerek composer raporlama pipeline'ını (Phase 24 A2) etkileyebilir.

## Neden Override?

Sektör template'leri genel benchmark değerleri sağlar (örn: FMCG için CPC `low_warn = 1.5 TL`). Ancak markanızın gerçek operasyonel sınırları farklı olabilir:

* **Premium otomotiv** markası → CPC eşiği daha yüksek (target audience pahalı)
* **Niche e-ticaret** markası → CTR `high_info` daha düşük (conversion yerine awareness)
* **Telco MNP campaign** → ROI `low_warn` agresif (churn prevention öncelik)

<Tip>
  **Override yazılmayan metrik için sektör default kullanılır.** Sadece marka için anlamlı olan kanal × metrik kombinasyonlarına override girin — diğer hepsi otomatik fallback.
</Tip>

## Yetki

| Rol              | Yetki                                             |
| ---------------- | ------------------------------------------------- |
| `CEO`            | ✅ Override CRUD (Create / Read / Update / Delete) |
| `CMO`            | ✅ Override CRUD                                   |
| `Analytics`      | 👁️ Read-only (override'ları görür, düzenleyemez) |
| `Agency`         | ❌ Erişim yok (org admin yetkisi yok)              |
| `platform_admin` | ✅ Tüm org'larda override yönetebilir              |

<Warning>
  `Agency` rolündeki kullanıcılar **müşteri markası adına** override giremez. Override güncellemesi gerekiyorsa org içindeki `CEO`/`CMO` rolüne sahip biri yapmalıdır.
</Warning>

## UI Flow

<Steps>
  <Step title="Settings sayfasına git">
    Sol menüden **Settings** → 6. tab **Benchmark Override** (`TrendingUp` icon).
  </Step>

  <Step title="Marka seçici (multi-brand org'larda)">
    `brands.length > 1` ise dropdown render edilir. Hangi markaya override yazacağınızı seçin. Single-brand org'larda otomatik aktif marka.
  </Step>

  <Step title="Override tablosu">
    Mevcut override'lar flat tablo halinde listelenir:

    ```
    Channel        Metric     low_warn  low_info  high_info  high_warn
    google_ads     cpc        0.5       1.0       3.0        5.0
    meta_ads       ctr        0.01      0.02      0.05       0.08
    tv             roi        0.8       1.0       2.5        4.0
    ```

    Boş tablo "No overrides for this brand yet" empty state gösterir.
  </Step>

  <Step title="Add Override (dialog form)">
    **"+ Add Override"** butonu → dialog form:

    * **Channel** dropdown (Google Ads, Meta Ads, TV, OOH, Linear TV, TikTok, YouTube, vb. — `ChannelType` enum)
    * **Metric** dropdown (CPC, CTR, ROI, conversion\_rate, vb.)
    * **4 threshold input**: `low_warn`, `low_info`, `high_info`, `high_warn` (numeric, validation sıralama kuralı uygular)

    Submit → backend `PATCH /admin/brands/{brand_id}/benchmark-overrides` veya `PATCH /brands/{brand_id}/benchmark-overrides` (Phase 24 A3 org-scoped).
  </Step>

  <Step title="Row actions">
    Her satırda **Edit** (dialog edit mode) ve **Delete** (ConfirmDialog onayı) butonları.
  </Step>

  <Step title="Clear all">
    **"Clear All"** butonu tüm override'ları siler (ConfirmDialog onayı). Sektör default'lara geri döner.
  </Step>
</Steps>

## Channel × Metric Matrisi

Aşağıdaki kanal-metrik kombinasyonları desteklenir:

| Channel          | Desteklenen Metrikler                                   |
| ---------------- | ------------------------------------------------------- |
| `google_ads`     | `cpc`, `ctr`, `roi`, `conversion_rate`, `quality_score` |
| `meta_ads`       | `cpc`, `ctr`, `roi`, `conversion_rate`, `frequency`     |
| `tiktok_ads`     | `cpc`, `ctr`, `roi`, `engagement_rate`                  |
| `youtube`        | `cpv`, `ctr`, `roi`, `view_rate`                        |
| `tv` (Linear TV) | `cpm`, `roi`, `reach`, `frequency`                      |
| `ooh`            | `cpm`, `roi`, `impressions`                             |
| `print`          | `cpm`, `roi`                                            |
| `affiliate`      | `roi`, `conversion_rate`, `cps`                         |

<Note>
  Yeni kanal eklenirse (örn: connected TV, programmatic) backend `ChannelType` enum'u güncellenir, frontend otomatik yeni kanalı dropdown'da gösterir.
</Note>

## Ordering Rule

Threshold değerleri **artan sırada** olmalı:

```
low_warn < low_info < high_info < high_warn
```

**Anlam:**

* `low_warn` → bu değerin altı **kırmızı uyarı** (KPI çok düşük, acil aksiyon)
* `low_info` → bu değerin altı **sarı bilgi** (KPI düşük, izleme)
* `high_info` → bu değerin üstü **yeşil bilgi** (KPI iyi, optimum aralık)
* `high_warn` → bu değerin üstü **mavi uyarı** (KPI çok yüksek, anomali kontrolü)

<Warning>
  Sıralama hatası `BENCHMARK_OVERRIDE_ORDER_INVALID` exception fırlatır. Dialog form submit öncesi Zod validation ile yakalanır; backend Pydantic schema'sı double-check yapar. Detay: [Sorun Giderme](/troubleshooting#benchmark_override_order_invalid).
</Warning>

## JSON Merge Stratejisi (Deep Merge)

Override yazıldığında backend **deep merge** uygular — mevcut override'ları silmez, yalnızca yeni gönderilen path'i günceller:

```json theme={null}
// Mevcut benchmark_overrides
{
  "google_ads": { "cpc": { "low_warn": 0.5, "low_info": 1.0, "high_info": 3.0, "high_warn": 5.0 } }
}

// PATCH body
{
  "google_ads": { "ctr": { "low_warn": 0.01, "low_info": 0.02, "high_info": 0.05, "high_warn": 0.08 } }
}

// Sonuç (deep merge)
{
  "google_ads": {
    "cpc": { "low_warn": 0.5, "low_info": 1.0, "high_info": 3.0, "high_warn": 5.0 },
    "ctr": { "low_warn": 0.01, "low_info": 0.02, "high_info": 0.05, "high_warn": 0.08 }
  }
}
```

**Null sentinel ile silme:**

```json theme={null}
// google_ads.cpc override'ını sil
{
  "google_ads": { "cpc": null }
}
```

Backend `null` değeri sentinel olarak kabul eder ve ilgili metric/channel entry'sini siler. Kullanıcı kazara veri kaybetmesin diye **PUT replace yerine PATCH merge** tercih edildi.

## Composer Integration (Phase 24 A2)

Override yazıldıktan sonra **manuel re-run gerekmez**. Composer pipeline her rapor üretiminde `lookup_benchmark` helper'ı çağırır:

1. Composer query brand'i (Phase 24 A2 loader propagation pattern) → `benchmark_overrides` JSONB additive
2. `lookup_benchmark(channel, metric)` 3-way dispatch:
   * Override library off → `None` (sektör default)
   * Override library on + brand override off → `get_threshold` (sektör default)
   * Her ikisi on → `get_threshold_with_brand_override` (marka-spesifik değer)
3. Rapor render edilirken doğru eşik değer otomatik kullanılır

<Note>
  `FEATURE_BRAND_BENCHMARK_OVERRIDE` flag `true` (Phase 24 A2'de canlıya alındı). Override aktif konsume ediliyor; cache invalidation gerekmez. Detay: [Composer LLM Cache Invalidation](/admin/cache-invalidation).
</Note>

## Audit Log

Her override işlemi audit log'a yazılır:

* `brand_benchmark_override_updated` — Add veya Edit
* `brand_benchmark_override_cleared` — Delete veya Clear All

Log fields: `user_id`, `brand_id`, `channel`, `metric`, `before_value`, `after_value`, `timestamp`.

## Sorun Giderme

### `BENCHMARK_OVERRIDE_ORDER_INVALID`

**Sebep:** Threshold değerleri yanlış sırada.

**Çözüm:** Değerleri artan sırada gir: `low_warn < low_info < high_info < high_warn`. Detay: [Sorun Giderme](/troubleshooting#benchmark_override_order_invalid).

### Override yazdım ama raporda görmüyorum

**Olası nedenler:**

1. **Cache'lenmiş eski rapor** → Yeni rapor üret (`L7 Reports` → "CEO Brief Oluştur")
2. **Yanlış brand'e yazdın** → Marka seçici aktif markayı kontrol et
3. **Flag off (geçmiş bir snapshot)** → `FEATURE_BRAND_BENCHMARK_OVERRIDE` flag aktif (`v0.7.58` sonrası canlı)

### Override'lar geri geldi (clear all sonrası)

**Sebep:** Clear All yerine Edit'lediniz — backend deep merge mevcut entry'leri korur.

**Çözüm:** Her override'ı **null sentinel** ile manuel sil veya **Clear All** butonunu kullan.

## Sonraki Adım

<CardGroup cols={2}>
  <Card title="Multi-brand Portföy" icon="layer-group" href="/settings/multi-brand">
    Birden fazla markayı tek hesaptan yönet
  </Card>

  <Card title="L2 Model Studio" icon="cog" href="/6-istasyon/l2-model-studio">
    Sektör template + adstock/saturation prior'lar
  </Card>
</CardGroup>
