# Kapsama matrisi — `20 Planlamaci Sorgulama`

*02.08.2026 · Tasarım: `design/20 Planlamaci Sorgulama.dc.html` · Uygulama: `resources/js/pages/Office/Planning/Query.vue` + `app/Queries/Office/StaffCompliance.php`*

Tasarım dosyası implementasyondan sonra tekrar açıldı ve satır satır çıkarıldı (Tasarım Uygulama Protokolü §3).

⛔ **Karar (Sets, 02.08.2026):** ekran **bilgi verir**, eğitim doğurmaz. Firma ile teklif sürecine girilmeden eğitim/planlama olmaz; bu yüzden tasarımdaki "Eğitim Planına Dönüştür" iki çıkışa ayrıldı ve **hiçbir kişi/firma bağı taşımıyor**.

## Sorgulama ekranı

| # | Tasarım öğesi | ✓/⚠/❌ | Kanıt |
|---|---|---|---|
| 1 | Kırıntı yolu "Kokpit / Sorgulama" | ✓ | `Query.vue` `PageHeader :trail` |
| 2 | Başlık + "talep ve potansiyeli keşfet" alt cümlesi | ✓ | `trainings.query.title` / `intro` — ⚠ cümle **kararla değişti**: "eğitim, firmayla görüşülüp talep alındıktan sonra doğar" |
| 3 | "SORGU KOŞULLARI · koşullar VE ile bağlanır" | ✓ | `conditions` / `conditions_note`; `StaffCompliance::matches()` koşulları VE ile uygular |
| 4 | Kayıtlı görünüm çipleri ("Kocaeli — dolanlar", "Marmara 90 gün", "3 ay kuralı") | ❌ | **yok** — 20-a |
| 5 | "Görünümü Kaydet" | ❌ | **yok** — 20-a |
| 6 | "Dışa Aktar" | ❌ | **yok** — 20-b |
| 7 | İl filtresi (çoklu, çıkarılabilir çip) | ✓ | `MultiSelect` + `il[]` adres parametresi |
| 8 | Eğitim türü filtresi | ✓ | `egitim[]` |
| 9 | Süre durumu filtresi (Doldu / ≤ 90 gün) | ✓ | Üç durum düğmesi: `lapsed` / `due` / `awaiting` — ⛔ eşik sabit 90 değil, `complianceWarningDays()` ayarı |
| 10 | Firma filtresi | ✓ | `firma[]` — yalnız okuyucunun erişebildiği firmalar |
| 11 | "＋ Koşul" | ⚠ | Dört koşul da ekranda açık duruyor; dinamik koşul ekleme yok — 20-c |
| 12 | "Sorgula" butonu | ✓ | `ask()` — koşullar **adrese** yazılır (paylaşılabilir bağlantı) |
| 13 | "SONUÇ 238 personel" | ✓ | `result.total` |
| 14 | "SÜRESİ DOLMUŞ 96" | ✓ | `summary.lapsed` |
| 15 | "90 GÜN İÇİNDE 142" | ✓ | `summary.due` (eşik ayardan) |
| 16 | "FİRMA 54" | ✓ | `summary.companies` |
| 17 | "EN YOĞUN İHTİYAÇ Görev 8 (84) · Görev 4 (61)" | ✓ | `summary.heaviest` — ilk iki ihtiyaç |
| 18 | "12 kayıt seçildi" şeridi | ✓ | `picked` şeridi |
| 19 | "Eğitim Planına Dönüştür →" | ⚠ | **Karar gereği değişti**: "Açık eğitim taslağı oluştur" — `/egitimler/planla?il=&egitim=&kisi=`; taslak **kişi/firma taşımaz**, açık eğitim olur |
| 20 | "Satışa Fırsat Olarak Aktar" | ⚠ | **Karar gereği değişti**: "Satışa ilet — müşteriyle görüşülsün" → `TaskKind::ComplianceOutreach`; ⛔ "teklif hazırla" değil |
| 21 | "Seçimi bırak" | ✓ | `picked = []` |
| 22 | Tablo başlıkları: PERSONEL / FİRMA·LOKASYON / İHTİYAÇ / BİTİŞ ↓ / DURUM | ✓ | `Query.vue` tablo |
| 23 | Satırda maskeli kimlik no (`482•••••316`) | ✓ | `Masker::nationalId()` — ⛔ liste ekranı kimlik okuma eylemi değildir (AD-16) |
| 24 | Firma + lokasyon iki satır | ✓ | `customer` + `location` · `province` |
| 25 | "Görev 8 yenileme" / "Görev 2 ilk eğitim" | ✓ | `need` + `renewal` bayrağı; sertifikası olmayan için "İlk eğitim" |
| 26 | Bitiş tarihi + "74 gün geçti" / "15 gün kaldı" | ✓ | `days` + `days_ago` / `days_left` |
| 27 | Durum rozetleri: Süresi Doldu / Süresi Yaklaşıyor / Eğitim Bekliyor | ✓ | Üç ton — ⛔ ölçek değil: işe yeni giren **başarısızlık değildir** |
| 28 | Sıralama: bitişe göre | ✓ | `usort` — en acil önce |
| 29 | "238 kayıttan 1–4 · ‹ 1 2 … 60 ›" | ✓ | `page` / `pages` + Önceki/Sonraki (sayfa 25 kayıt) |
| 30 | "firma bazında grupla ▾" | ❌ | **yok** — 20-d |
| 31 | Satır seçimi (checkbox) + sayfa seçimi | ✓ | `togglePick` / `togglePage` |
| 32 | 375px | ✓ | Tablo kendi kutusunda yatay kayar; filtre ızgarası `md:grid-cols-2 xl:grid-cols-4` |

## Erişim logu (karar, tasarımda yok)

| # | Kural | ✓ | Kanıt |
|---|---|---|---|
| 33 | Sorgu tek satır loglanır | ✓ | `AccessLogger::recordQuery('staff_compliance_query', …)` |
| 34 | Log koşulları taşır | ✓ | `context.filters` |
| 35 | Log sonuç **kimlik listesini** taşır | ✓ | `context.result_ids` — sayfayı değil, **tüm sonucu** |
| 36 | Log ad/TC/firma taşımaz | ✓ | Test: `StaffQueryTest` — "no name, anywhere in the row" |
| 37 | Kişi başına satır yazılmaz | ✓ | Test: "does not write one access row per person" (3 kişi → 1 satır) |

## Planlama kuyruğu (tasarımın ikinci yarısı)

| # | Tasarım öğesi | ✓/⚠/❌ | Kanıt |
|---|---|---|---|
| 38 | "Planlama kuyruğu — onaylı teklifler + planlama talepleri" | ⚠ | Talepler `/talepler` ekranında (`Requests/Index.vue`, tasarım `34`); **onaylı teklif sekmesi ayrı bir kuyrukta değil** — 20-e |
| 39 | SLA rozetleri ("SLA 2 GÜN" / "SLA AŞILDI") | ⚠ | Onay kuyruğunda SLA var; planlama kuyruğunda yok — 20-e |
| 40 | "Planlamaya Başla →" / "Mevcut Eğitime Bağla" | ⚠ | Talepten planlama var (`from_request`); "mevcut eğitime bağla" yok — 20-f |
| 41 | Engel satırları ("bölgede müsait eğitmen yok", "asgari katılımcı sınırında") | ❌ | **yok** — 20-f |
| 42 | "Bölgeye Duyuru Aç" | ❌ | **yok** — açık eğitim duyurusu yazılmadı — 20-g |

## Kapanmamış satırlar — karar gerekiyor (Onay Kuralı 6)

| Kod | Satır | Durum | Soru |
|---|---|---|---|
| **20-a** | #4, #5 kayıtlı görünüm | ❌ | Kayıtlı sorgu görünümleri bu turda mı, ayrı ticket mı? (kişiye mi, herkese mi ait olacak?) |
| **20-b** | #6 dışa aktarma | ❌ | CSV/Excel çıktısı verilecek mi? ⚠ Verilirse kişisel veri **dosya olarak** dışarı çıkar — erişim logu ve filigran kararı gerekir |
| **20-c** | #11 "＋ Koşul" | ⚠ | Dört sabit koşul yeterli mi, dinamik koşul kurucusu gerekli mi? |
| **20-d** | #30 firma bazında gruplama | ❌ | Sonuç firma bazında katlanabilsin mi? |
| **20-e** | #38, #39 planlama kuyruğu | ⚠ | Onaylı teklifler ayrı bir "kuyruk" ekranında mı toplanmalı, yoksa mevcut talepler ekranı yeterli mi? |
| **20-f** | #40, #41 "mevcut eğitime bağla" + engel satırları | ⚠ | Onaylı teklifin katılımcıları açık kontenjanlı mevcut eğitime bağlanabilsin mi? |
| **20-g** | #42 bölgeye duyuru | ❌ | Açık eğitim duyurusu (müşterilere toplu bildirim) ayrı iş mi? |
