# Yeni arayüz fiş özelleştirme — Posmanager

## Amaç ve durum

Posmanager'da yetkili firma yöneticisi fişin sabit alanlarını göster/gizle yapabilecek ve özel alt not ekleyebilecek. Tercihler yalnız Poscloud'un henüz yayında olmayan yeni satış arayüzünde kullanılacak; eski POS fişleri değişmeyecek.

Durum (2026-09-22): Posmanager kod uygulaması tamamlandı; DB'siz kontroller geçti. Gerçek DB/API, tarayıcı/Livewire yaşam döngüsü ve uçtan uca baskı doğrulaması yapılmadı; ayrı açık izin bekliyor. UI doğrulanmış veya dağıtıma hazır kabul edilmemelidir. Bu doküman Posmanager değişikliklerini kapsar; Poscloud desteği o projenin aynı adlı görev dokümanında açıklanır. Commit oluşturulmadı.

## Uygulanan değişiklikler

- `app/Livewire/ReceiptDesign.php`: Mevcut takımda Posmanager admin ve seçili POS firması erişimi ilk yüklemede, hydration, save ve preview sırasında yeniden kontrol edilir. Kilitli firma ve takım kimliği eski sekmeden farklı firma/takıma işlem yapılmasını engeller.
- `resources/views/settings/receipt-design.blade.php` ve `resources/views/livewire/receipt-design.blade.php`: Dokuz sabit görünürlük alanı (alt not dahil), 500 karakterlik düz metin alt not, stone renkli açık Önizle/Kaydet düğmeleri ve yeni POS kapsamı açıklaması eklendi. Otomatik kayıt yoktur; ürünler ve net toplam gizlenemez. Görünürlük checkbox'ları değiştiğinde önizleme sunucuda otomatik yenilenir (`updatedOptions` nested key ile `visibility.*` değişimini yakalar); alt not yazımı yalnızca mevcut önizlemeyi bayat işaretler ve manuel Önizle bekler. Otomatik yenileme isteği sırasında checkbox grubu devre dışı kalır ve "İşlem sürüyor…" göstergesi görünür.
- `app/Http/Controllers/SettingsController.php`, `routes/web.php`, `resources/views/settings/index.blade.php`: `settings.receipt-design` rotası ve ayarlar bağlantısı eklendi. İlk yetki kontrolü, varsayılan firma seçebilen view composer'dan önce çalışır. Firma/API anahtarı döndüren ortak yetki metodu Livewire'ın çağrılabilir public action yüzeyinde değildir.
- `app/Services/ReceiptDesignOptions.php`: Sabit varsayılanlar ve tam JSON sözleşmesi için küçük, DB'siz yardımcı eklendi. Kayıt/önizleme isteklerinde fazladan/eksik alanlar, boolean olmayan değerler ve yanlış sürüm reddedilir. Okumada eksik/bozuk/desteklenmeyen kayıt varsayılanlara döner; v1 kaydındaki geçerli alanlar korunur, eksikler ve yanlış türde alanlar Poscloud ile aynı şekilde varsayılanlarla tamamlanır.
- `app/Services/PosCloudService.php`: Yetkili firma ID ve anahtarı açıkça verilerek sunucudan `POST /receipt-design/preview` çağrılır; 10 saniye timeout, 5 saniye bağlantı sınırı, yönlendirme kapalı. Yeni önizleme akışı payload/anahtar/ham hata loglamaz veya tarayıcıya taşımaz. HTML escaped `srcdoc`, boş `sandbox` ve sabit boyutlu iframe içinde gösterilir. Önizleme kayıt/baskı yapmaz; kayıt API'den bağımsızdır.
- `app/Livewire/Settings.php`: `eadisyon_receipt` generic form state/default sorgusundan çıkarıldı. Doğrudan/iç içe/büyük harf/son boşluk varyantları engellendi; DB collation eşdeğerleri için SQL dışlaması da eklendi. Diğer ayar varsayılanları ve boolean dönüşümü korunur.
- `tests/Unit/ReceiptDesignTest.php`: Laravel uygulamasını boot etmeyen plain PHPUnit testleri eklendi. PDO erişimini atan koruma, yalnız mock SQL ve gerçek HTTP'yi engelleyen fake kullanılır; mevcut PROD bağlantılı test altyapısı/config değiştirilmedi.

## Veri sözleşmesi ve sahiplik

Poscloud `settings` tablosunda `relation_type=company`, `relation_id=POS firma ID`, `key=eadisyon_receipt`; `value` JSON metni:

```json
{"version":1,"visibility":{"receipt_number":true,"table":true,"date":true,"time":true,"payment_type":true,"discount_summary":true,"tax":true,"payments":true,"footer_note":true},"footer_note":""}
```

Kayıt `mysql-remote` bağlantısında, aynı transaction içinde firma satırı kilitlenerek üç alanla kapsamlanmış Query Builder update-or-insert ile yapılır. Kaynak şemada setting ID/unique indeks tanımı yok; mükerrer mevcut kayıt otomatik silinmez veya birleştirilmez. Genel `Setting.value` JSON cast'i eklenmez.

Ürünler/hesap tutarı zorunlu; alanlar sabit; not düz metin. Önizleme taslağı kaydetmez. Render sorumluluğu Poscloud'un yeni Blade şablonundadır; Posmanager'a ikinci şablon kopyalanmaz. Kayıt önizleme servisinin erişilebilirliğine bağlı değildir.

Apper auth ve erişim kayıtları Posmanager kimlik doğrulamasında kullanılmaya devam eder. POS tercihi Apper DB'ye yazılmaz; bu görev `admin.apper` ya da Poscloud migration değişikliği gerektirmez.

## Doğrulama ve izin

Her iki uygulama ve DB yapıları PROD. Her DB işlemi (salt okunur dahil), API auth sorgusu ve DB'ye erişen test/tarayıcı akışı ayrı açık izin gerektirir. Mevcut PosCloudService üretim API adresini seçer; testlerde gerçek dış HTTP engellenmelidir. Plan/kod uygulama onayı DB veya dağıtım izni değildir.

- [x] Değişen PHP dosyalarında `php -l`; hata yok. `git diff --check` temiz; gerçek diff incelendi.
- [x] İzole PHPUnit: 57 test / 130 assertion geçti. Gerçek DB/PDO/HTTP kullanılmadı. Mevcut Sanctum `HasApiTokens.php:46` PHP 8.4 nullable-parametre deprecation uyarısı var; vendor değiştirilmedi. İki uygulamanın saf normalizasyon yardımcıları ayrıca 15 ortak örnekte aynı sonucu verdi.
- [x] Mock kontroller: eksik seçim/takım, admin veya firma erişimi yokluğu, firma değişimi ve aynı firma ID'sinde takım değişimi reddedildi. Kilit attribute'ları kaynak düzeyinde doğrulandı.
- [x] Mock SQL: ilk insert, değişmeyen update, firma kilidi → scoped setting kilidi sırası ve duplicate reddi; gerçek transaction/eşzamanlılık testi değildir.
- [x] Generic özel anahtar engeli ve yüklenen state dışlaması; diğer ayar varsayılanı/boolean davranışı.
- [x] Fake HTTP: doğrudan JSON/Bearer, süre sınırları, hata/timeout/bozuk yanıt, anahtar gizliliği ve önizlemenin yazmaması. Düz metin/Unicode/500 karakter, bozuk sürüm ve tipler doğrulandı. Iframe markup kontrolü tarayıcı güvenlik testi değildir.
- [ ] Gerçek auth/DB ile kaldırılan erişim ve Livewire locked-property/snapshot/multi-tab akışları — izin bekliyor.
- [ ] Gerçek DB'de ilk/aynı değerli/eşzamanlı kayıt, duplicate/transaction/rollback ve kapsam doğrulaması — izin bekliyor.
- [ ] Poscloud endpoint entegrasyonu, tarayıcıda önizleme invalidation/sandbox/scroll, HTML benzeri notun düz metin baskısı ve yönetim → önizleme → kaydet → yeni POS baskısı; eski fiş değişmezliği — izin bekliyor.

Çalıştırılan izole test komutu (uygulama bootstrap ve mevcut phpunit config kullanılmaz):

```sh
php /home/ugur-karagoz/Projects/posmanager.apper/vendor/bin/phpunit --no-configuration --do-not-cache-result --display-deprecations --bootstrap /home/ugur-karagoz/Projects/posmanager.apper/vendor/autoload.php /home/ugur-karagoz/Projects/posmanager.apper/tests/Unit/ReceiptDesignTest.php
```

Mevcut `PosCloudService::createCustomerTransaction` kodunda anahtarın ilk karakterlerini/payload/ham yanıtı loglayan eski davranış görüldü. Yeni önizleme bunu kullanmaz; bu görev kapsamında eski akış refactor edilmedi. Ayrı güvenlik takibi önerilir.

Önce Poscloud'un yeni endpoint/şablon desteği, ardından bu ekran dağıtılmalıdır; dağıtım ayrı izinle yapılır.
