# Raporlar Sistemi Analizi - ReportsController

## Genel Bakış

`ReportsController.php`, poscloud.apper projesindeki raporlama sisteminin merkezidir. Bu controller, restoran POS sistemi için 5 farklı rapor türünü yönetir ve kapsamlı filtreleme, istatistik hesaplama ve Excel dışa aktarma özellikleri sunar.

---

## 1. Rapor Türleri

Controller **5 farklı rapor türünü** yönetir:

### 1.1 Satış Raporu (`sales()`)
- **Amaç:** Ürün bazlı satış aggregasyonu
- **Gruplama:** Ürün ID'sine göre gruplandırılmış
- **Veri:** Toplam fiyat, miktar, KDV, hizmet bedeli
- **Kullanım:** Hangi ürünlerin ne kadar sattığını görmek için

### 1.2 Garson Raporları (`waiterReports()`)
- **Amaç:** Garson/personel bazlı performans analizi
- **Gruplama:** Kullanıcı (garson) ID'sine göre gruplandırılmış
- **Veri:** Her garsonun toplam satışları ve sipariş sayıları
- **Kullanım:** Personel performans değerlendirmesi için

### 1.3 Adisyon Raporları (`sessionReports()`)
- **Amaç:** Masa/checkout seanslarının özeti
- **Model:** `Sale` modeli (sipariş grupları)
- **Veri:** Brüt/net tutarlar, ödeme tipleri, indirimler, ikramlar
- **Kullanım:** Masa kapanış raporları için

### 1.4 Sipariş Raporları (`orderReports()`)
- **Amaç:** Bireysel sipariş detayları
- **Veri:** Her siparişin tam detayı (ürün, garson, masa, kategori)
- **Kullanım:** Detaylı sipariş takibi ve analizi için

### 1.5 İptal Raporları (`cancelReports()`)
- **Amaç:** İptal edilen siparişlerin raporu
- **Filtre:** Sadece iptal edilmiş siparişler (`cancelled()` scope)
- **Veri:** İptal eden kullanıcı, iptal nedeni, tarih
- **Kullanım:** İptal analizi ve denetim için

---

## 2. Ortak Rapor Oluşturma Deseni

Tüm raporlar tutarlı bir **7 adımlı desen** izler:

### Adım 1: Tarih Aralığı Belirleme

```php
// Öncelik sırası: Finansal Gün > Manuel Tarih Aralığı > Varsayılan (bugün)
if (Input::get('financialDay')) {
    $stat = FinancialDay::where('day', ...)->firstOrfail();
    $filters['beginningDate'] = $stat->starting;
    $filters['endingDate'] = $stat->ending;
} else {
    [$start, $end] = parseDateRange(Input::get('dateRange'), 'd.m.Y H:i');
    $filters['beginningDate'] = $start ?: FinancialDay::getCreateActiveEntry()->starting;
    $filters['endingDate'] = $end ?: Carbon::now();
}
```

**Özellikler:**
- Finansal gün seçilirse, o günün başlangıç/bitış saatleri kullanılır
- Manuel tarih aralığı parse edilir (format: `d.m.Y H:i`)
- Varsayılan olarak aktif finansal günün başlangıcı ve şu anki zaman kullanılır

### Adım 2: Query Scope'ları ile Sorgu Oluşturma

Her rapor Laravel query scope'larını kullanır:

- **`onlyTrashed()`** - Sadece soft-delete edilmiş kayıtlar (tamamlanmış satışlar/siparişler)
- **`forGross()`** - İptal edilmiş ödemeleri hariç tutar (`PayableTrait`'ten)
- **`filter($filters)`** - Dinamik filtreler uygular (tarih, kategori, ürün, ödeme tipi, vb.)
- **Ek scope'lar** - Örn: `cancelled()` iptal raporları için

### Adım 3: Veri Aggregasyonu veya Listeleme

**Aggrege raporlar için** (satış, garson):
```php
$orders = Order::onlyTrashed()
    ->with('product', 'trackingSection', 'category')
    ->forGross()
    ->filter($filters)
    ->select([
        DB::raw('SUM(total_price) as total_price'),
        DB::raw('SUM(quantity) as quantity'),
        DB::raw('SUM(vat * quantity) as vat'),
        DB::raw('SUM(service_fee * quantity) as service_fee'),
        'product_id', 'tracking_section_id', 'payment_type', 'category_id',
    ])
    ->orderBy('total_price', 'DESC')
    ->groupBy('product_id');
```

**Detaylı raporlar için** (sipariş, seans, iptal):
```php
$orders = Order::onlyTrashed()
    ->forGross()
    ->with('user', 'sale.destination', 'product', 'trackingSection', 'category')
    ->filter($filters)
    ->orderBy('id', 'DESC');
```

### Adım 4: Dışa Aktarma (Export) İşleme

```php
if (Input::get('export')) {
    $fileName = Str::slug(label('platform') . '-' . company()->name . '-' . 
                          sectionName("admin.sales.sales") . '-' . Carbon::now()->toDateString());
    return (new SaleReportExport($orders->get()))->download("$fileName.xlsx");
}
```

Laravel Excel kullanarak özel formatlayıcılarla Excel dosyası oluşturur.

### Adım 5: Sayfalama (Pagination)

```php
$orders = $orders->paginate(Input::get('perPage', 20));
$orders->setPath(\Request::fullUrl()); // Filtre parametrelerini sayfalama linklerinde koru
```

### Adım 6: İstatistik Hesaplama

Ayrı bir query özet istatistikleri hesaplar:
```php
$stats = Order::onlyTrashed()->forGross()->filter($filters)
    ->select('total_price', 'quantity', 'payment_type', 'vat', 'service_fee')
    ->get();
$stats = getOrderStats($stats); // Helper fonksiyon
```

### Adım 7: Filtre Seçenekleriyle View Render

View'a veri ve filtre dropdown'ları gönderilir:
- Ürünler, Kategoriler, Masalar, Müşteriler, Kullanıcılar
- Ödeme tipleri, Takip bölümleri
- Sayfalama seçenekleri

---

## 3. Temel Teknik Bileşenler

### 3.1 İstatistik Helper Fonksiyonları

#### `getOrderStats($orders)` - Sipariş Seviyesi İstatistikler

**Hesapladıkları:**
- Genel toplamlar (fiyat, miktar)
- Ödeme tipi kırılımı (nakit, kredi kartı, çek, online, sabee, ikram, kredi)
- KDV ve hizmet bedeli toplamları
- İç içe geçmiş array yapısı döndürür

**Dönen Yapı:**
```php
[
    'overall' => ['price' => 0, 'numItems' => 0],
    'cash' => ['price' => 0, 'numItems' => 0],
    'credit-card' => ['price' => 0, 'numItems' => 0],
    'ticket' => ['price' => 0, 'numItems' => 0],
    'online' => ['price' => 0, 'numItems' => 0],
    'sabee' => ['price' => 0, 'numItems' => 0],
    'credit' => ['price' => 0, 'numItems' => 0],
    'treat' => ['price' => 0, 'numItems' => 0],
    'vat' => ['price' => 0],
    'service-fee' => ['price' => 0],
]
```

#### `getSaleStats($sales)` - Satış Seviyesi İstatistikler

**Hesapladıkları:**
- Net ve brüt fiyatlar
- Satış başına sipariş sayısı
- Ödeme tipi kırılımı
- İkramlar, indirimler, iptaller
- Sipariş istatistiklerinden daha detaylı

**Dönen Yapı:**
```php
[
    'overall' => ['net_price' => 0, 'gross_price' => 0, 'numItems' => 0],
    'cash' => ['price' => 0, 'numItems' => 0],
    'credit-card' => ['price' => 0, 'numItems' => 0],
    // ... diğer ödeme tipleri
    'vat' => ['price' => 0],
    'service-fee' => ['price' => 0],
    'treat' => ['price' => 0, 'numItems' => 0],
    'discount' => ['price' => 0, 'numSales' => 0],
    'cancel' => ['price' => 0, 'numItems' => 0],
]
```

### 3.2 Query Scope'ları

#### `scopeFilter(Builder $query, $filters)` - Order Model

**Desteklenen Filtreler:**
- **Tarih aralığı** (`beginningDate`, `endingDate`) - `deleted_at` sütunu üzerinden
- **Kullanıcı/Garson** (`userId`)
- **Kategori** (`categoryIds`) - Tersine çevirme desteğiyle (`categoryIdsInverted`)
- **Ürün** (`productIds`) - Tersine çevirme desteğiyle (`productIdsInverted`)
- **Masa** (`tableId`) - Sale ilişkisi üzerinden
- **Ödeme tipi** (`payment_type`, `paymentTypes`)
- **Stok item** (`stockItemId`) - Ürün mixin'leri üzerinden
- **Takip bölümü** (`tracking_section_id`)

#### `scopeForGross()` - PayableTrait

- İptal edilmiş ödemeleri hariç tutar: `where('payment_type', '!=', PAYMENT_TYPE['cancel'])`
- Brüt satış hesaplamaları için kullanılır

### 3.3 Soft Deletes Stratejisi

**Önemli Tasarım Deseni:**
- `onlyTrashed()` kullanılır çünkü tamamlanan satışlar/siparişler kapatıldığında soft-delete edilir
- "Silinmiş" anlamı "tamamlanmış/finalize edilmiş"tir
- Geçmiş verileri korurken aktif tabloları temiz tutar
- `withTrashed()` ile silinmiş kayıtlara erişim mümkündür

---

## 4. Dışa Aktarma Sistemi

**Laravel Excel (Maatwebsite)** paketi kullanılır:

### Export Sınıfları:
- `SaleReportExport` - Ürün satışları
- `WaiterReportExport` - Garson performansı
- `SessionReportExport` - Seans özetleri
- `OrderReportExport` - Detaylı siparişler
- `CancelReportExport` - İptaller

### Özellikler:
- Özel sütun formatlama (sayı formatları)
- Otomatik sütun boyutlandırma
- Kalın başlıklar
- Çevrilmiş sütun isimleri
- Soft-delete edilmiş ürünleri zarif şekilde işler

### Örnek: SaleReportExport
```php
public function headings(): array
{
    return [
        transUc('models.generic.name'),
        transUc('models.order.quantity'),
        transUc('models.order.total_price'),
        transUc('generic.financial.vat_percentage'),
        transUc('generic.financial.vat'),
        transUc('generic.financial.service_fee'),
        transUc('models.generic.category'),
        transUc('models.generic.tracking_section'),
    ];
}

public function columnFormats(): array
{
    return [
        'B' => NumberFormat::FORMAT_NUMBER,
        'C' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
        'D' => NumberFormat::FORMAT_NUMBER_00,
        'E' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
        'F' => NumberFormat::FORMAT_NUMBER_COMMA_SEPARATED1,
    ];
}
```

---

## 5. Finansal Gün Entegrasyonu

Sistem **Finansal Gün** konseptini destekler:

### Finansal Gün Nedir?
- Bir finansal gün birden fazla takvim gününü kapsayabilir
- Örnek: Restoran gece 04:00'te kapanıyorsa, bir finansal gün 2 günü kapsar
- `FinancialDay` tablosu bu dönemleri saklar

### Kullanım:
- `FinancialDay::getCreateActiveEntry()` - Aktif finansal dönemi alır
- Raporlar belirli finansal günlere göre filtrelenebilir
- `getFinancialDayPickerData()` - Seçilemeyen tarihleri hesaplar (kapalı günler)

### Finansal Gün Picker Verisi:
```php
$financialDayPickerData = [
    'startDate'     => $financialDays->first()->day->format('d/m/Y'),
    'endDate'       => $financialDays->last()->day->format('d/m/Y'),
    'datesDisabled' => [...], // Kapalı günler
];
```

---

## 6. Performans Değerlendirmesi

### ⚠️ Potansiyel Sorunlar:

1. **Constructor'da `sleep(1)`**
   - Her istekte yapay gecikme
   - Muhtemelen debug amaçlı bırakılmış, kaldırılmalı

2. **İstatistikler için İki Query**
   - İstatistikler için ayrı query, filtreleme mantığını tekrarlar
   - Database yükünü artırır

3. **Önbellekleme Yok**
   - İstatistikler her sayfa yüklemesinde yeniden hesaplanır
   - Sık kullanılan tarih aralıkları için cache eklenebilir

4. **N+1 Query Sorunları**
   - `with()` kullanılsa da, karmaşık ilişkiler sorun yaratabilir
   - Lazy loading kontrol edilmeli

5. **Büyük Veri Setleri**
   - Binlerce kayıt için export'ta chunking yok
   - Bellek sorunlarına yol açabilir

### ✅ Optimizasyon Önerileri:

- Yaygın tarih aralıkları için istatistikleri cache'le
- Karmaşık aggregasyonlar için database view'ları kullan
- Büyük export'lar için lazy loading implement et
- `sleep(1)` çağrısını kaldır
- Input validasyonu ekle
- Error handling iyileştir

---

## 7. Veri Akışı Özeti

```
Kullanıcı İsteği
    ↓
Input Filtreleri (tarih aralığı, kategoriler, ürünler, vb.)
    ↓
Tarih Çözümleme (Finansal Gün VEYA Manuel Aralık VEYA Bugün)
    ↓
Query Oluştur (Model + Scope'lar + Filtreler)
    ↓
┌─────────────────────────────────────┐
│ Export İsteği Var mı?               │
│  EVET → Excel Oluştur & İndir       │
│  HAYIR → Sayfalamaya Devam Et       │
└─────────────────────────────────────┘
    ↓
Sonuçları Sayfalandır (varsayılan 20/sayfa)
    ↓
İstatistikleri Hesapla (ayrı query)
    ↓
Filtre Seçeneklerini Yükle (ürünler, kategoriler, vb.)
    ↓
View'ı Veri ile Render Et
```

---

## 8. Mimari Desenler

### ✅ Güçlü Yönler:

1. **Tutarlılık** - Tüm rapor türlerinde aynı desen
2. **Yeniden Kullanılabilirlik** - Filter scope'ları paylaşılır
3. **Sorumluluk Ayrımı** - İstatistik hesaplamaları helper'larda
4. **Esnek Export Sistemi** - Laravel Excel ile genişletilebilir
5. **Finansal Gün Abstraksiyonu** - Gerçek dünya senaryolarını destekler
6. **Soft Deletes Pattern** - Geçmiş verileri korur

### ⚠️ Zayıf Yönler:

1. **Kod Tekrarı** - Rapor metodları arasında benzer kodlar
2. **Kullanılmayan Metod** - `getPaymentTypes()` tanımlı ama hiç kullanılmıyor (TODO yorumu var)
3. **Input Validasyonu Eksik** - Filtrelerde validasyon yok
4. **Input Facade Bağımlılığı** - Test edilmesi zor (dependency injection tercih edilmeli)
5. **Error Handling Eksikliği** - Edge case'ler için hata yönetimi yetersiz
6. **Magic Numbers** - Payment type ID'leri hardcoded

---

## 9. Dosya İlişkileri

### İlgili Controller:
- `app/Http/Controllers/Admin/Sales/ReportsController.php`

### Modeller:
- `app/Models/Order.php` - Siparişler
- `app/Models/Sale.php` - Satış seansları
- `app/Models/Product.php` - Ürünler
- `app/Models/Category.php` - Kategoriler
- `app/Models/Table.php` - Masalar
- `app/Models/User.php` - Kullanıcılar/Garsonlar
- `app/Models/Customer.php` - Müşteriler
- `app/Models/FinancialDay.php` - Finansal günler
- `app/Models/TrackingSection.php` - Takip bölümleri

### Export Sınıfları:
- `app/Exports/SaleReportExport.php`
- `app/Exports/WaiterReportExport.php`
- `app/Exports/SessionReportExport.php`
- `app/Exports/OrderReportExport.php`
- `app/Exports/CancelReportExport.php`

### Helper Fonksiyonlar:
- `app/helpers.php` - `getOrderStats()`, `getSaleStats()`

### Trait'ler:
- `app/Models/PayableTrait.php` - `scopeForGross()`, `scopeForNet()`

### View'lar:
- `resources/views/admin/sales/sales.blade.php`
- `resources/views/admin/sales/waiter-reports.blade.php`
- `resources/views/admin/sales/session-reports.blade.php`
- `resources/views/admin/sales/order-reports.blade.php`
- `resources/views/admin/sales/cancel-reports.blade.php`
- `resources/views/admin/sales/_partials/stats.blade.php`

---

## 10. Kullanım Senaryoları

### Senaryo 1: Günlük Satış Raporu
```
1. Admin panel → Satış Raporları
2. Tarih aralığı: Bugün
3. Kategori filtresi: Ana Yemekler
4. "Filtre Uygula" butonu
5. Ürün bazlı satış aggregasyonu görüntülenir
6. İstatistikler: Toplam satış, KDV, hizmet bedeli
7. Excel'e aktarma seçeneği mevcut
```

### Senaryo 2: Haftalık Garson Performansı
```
1. Admin panel → Garson Raporları
2. Tarih aralığı: Son 7 gün
3. Garson filtresi: Tüm garsonlar
4. Garson bazlı satış toplamları
5. En çok satış yapan garsonlar üstte
6. Performans değerlendirmesi için kullanılır
```

### Senaryo 3: Finansal Gün Kapanış Raporu
```
1. Admin panel → Seans Raporları
2. Finansal gün seçici: Dün
3. Masa kapanışları listelenir
4. Her masanın brüt/net tutarı
5. Ödeme tipi dağılımı (nakit, kredi kartı, vb.)
6. Muhasebe için günlük özet
```

### Senaryo 4: İptal Analizi
```
1. Admin panel → İptal Raporları
2. Tarih aralığı: Bu ay
3. İptal edilen tüm siparişler
4. İptal eden kullanıcı bilgisi
5. İptal nedenleri (varsa)
6. Kalite kontrol ve eğitim için kullanılır
```

---

## 11. Teknik Notlar

### PHP Versiyon Uyumluluğu:
- Laravel 9+ uyumlu
- PHP 8.2+ desteklenmeli

### Database:
- MySQL/MariaDB
- Soft deletes kullanımı yaygın
- `deleted_at` sütunu tamamlanmış kayıtları işaretler

### Paket Bağımlılıkları:
- `maatwebsite/excel` - Excel export/import
- `laravel/framework` - Core framework
- Carbon - Tarih/saat işlemleri

### Güvenlik:
- Admin yetkilendirmesi gerekli
- Company scope ile çoklu şirket desteği
- Input sanitization Laravel tarafından yapılır

---

## 12. Gelecek Geliştirmeler İçin Öneriler

### Kısa Vadeli:
1. `sleep(1)` kaldır
2. Input validasyonu ekle
3. `getPaymentTypes()` metodunu kullan veya sil
4. Error handling iyileştir

### Orta Vadeli:
1. İstatistik caching implement et
2. Export için queue job'ları kullan
3. Real-time rapor dashboard'u ekle
4. Grafik/chart entegrasyonu

### Uzun Vadeli:
1. Report builder pattern'e geçiş
2. Custom report template sistemi
3. API endpoint'leri ekle (mobile app için)
4. Advanced analytics (trend analysis, predictions)

---

## Sonuç

`ReportsController`, poscloud.apper projesinin kritik bir bileşenidir. Restoran işletmeleri için kapsamlı raporlama ve analiz araçları sunar. Mimari olarak tutarlı ve genişletilebilir bir yapıdadır, ancak performans optimizasyonu ve kod kalitesi açısından iyileştirme alanları bulunmaktadır.

Sistem, gerçek dünya restoran senaryolarını (finansal günler, çoklu ödeme tipleri, personel takibi) başarıyla modellemektedir ve Laravel'in güçlü özelliklerini (scopes, soft deletes, exports) etkili şekilde kullanmaktadır.

</file_content>
