# 🔥 ODJOO - Production-Level KDV Sistemi

## E-Fatura Uyumlu | Fintech Grade | Zero Float Error

---

## 📋 İçindekiler

1. [Genel Bakış](#genel-bakış)
2. [Temel Prensipler](#temel-prensipler)
3. [Mimari](#mimari)
4. [Kurulum](#kurulum)
5. [Kullanım](#kullanım)
6. [API Dokümantasyonu](#api-dokümantasyonu)
7. [Test](#test)
8. [Sorun Giderme](#sorun-giderme)

---

## Genel Bakış

Bu sistem, Türkiye e-Fatura standartlarına uygun, fintech kalitesinde bir KDV hesaplama motorudur.

### Özellikler

✅ **Zero Float Error** - Tamamen integer arithmetic  
✅ **Basis Point System** - %20 = 2000 basis points  
✅ **Line-Level Calculation** - Her satır bağımsız hesaplanır  
✅ **Compensation Algorithm** - E-fatura uyumlu telafi  
✅ **Discount Distribution** - Shopify seviyesinde indirim dağıtımı  
✅ **Dynamic VAT Rate** - Kullanıcı KDV oranını belirler  
✅ **Single Source of Truth** - NET_PRICE canonical değer  

---

## Temel Prensipler

### 1. Single Source of Truth

```
NET_PRICE (KDV Hariç) = TEK GERÇEK
```

Tüm hesaplamalar net fiyattan türetilir:
- KDV tutarı = net × rate
- Brüt tutar = net + kdv
- İndirim = net üzerinden uygulanır

### 2. Zero Float Arithmetic

```php
❌ YANLIŞ: $price = 83.33
✅ DOĞRU: $priceKurus = 8333
```

Tüm para değerleri **kuruş** (integer) olarak saklanır.

### 3. Basis Point System

```php
%1  = 100 basis points
%10 = 1000 basis points
%20 = 2000 basis points
```

Float KDV oranı kullanılmaz.

### 4. Line-Level Calculation

- Global hesaplama YOK
- Her satır bağımsız hesaplanır
- Sonra telafi algoritması uygulanır

---

## Mimari

### Core Classes

#### 1. MoneyHelper
Para birimi dönüşüm ve format işlemleri.

```php
MoneyHelper::toKurus("123.45")  // 12345
MoneyHelper::toTL(12345)        // 123.45
MoneyHelper::format(12345)      // "123,45 TRY"
```

#### 2. TaxEngine
KDV hesaplama motoru.

```php
// Net'ten KDV hesapla
$vat = TaxEngine::calculateVatFromNet(10000, 2000);
// 10000 kuruş × 2000 bp = 2000 kuruş (20 TL)

// KDV dahil'den net hesapla
$net = TaxEngine::calculateNetFromGross(12000, 2000);
// 12000 kuruş / 1.20 = 10000 kuruş (100 TL)

// Fatura hesapla
$result = TaxEngine::calculateInvoice($lineItems, 'net', $globalDiscount);
```

#### 3. DiscountEngine
İndirim dağıtım motoru.

```php
$lines = DiscountEngine::distributeGlobalDiscount(
    $lines, 
    $globalDiscountKurus, 
    $totalNetKurus
);
```

---

## Kurulum

### 1. Dosyaları Kopyalayın

```bash
classes/
  ├── MoneyHelper.php
  ├── TaxEngine.php
  └── DiscountEngine.php
```

### 2. Migration Çalıştırın

```bash
php migrate_to_integer_money.php
```

**UYARI:** Mutlaka yedek alın!

### 3. KDV Ayarını Yapın

`Ayarlar > KDV Hesaplama` menüsünden:
- KDV Hariç (varsayılan)
- KDV Dahil

---

## Kullanım

### Fatura Oluşturma

```php
require_once 'classes/MoneyHelper.php';
require_once 'classes/TaxEngine.php';

// Satır kalemleri hazırla
$lineItems = [
    [
        'unit_price' => MoneyHelper::toKurus("100.00"),
        'quantity' => 2,
        'vat_rate_basis' => TaxEngine::percentToBasis(20),
        'line_discount' => 0,
        'urun_id' => 1
    ]
];

// Hesapla
$result = TaxEngine::calculateInvoice($lineItems, 'net', 0);

echo "Net: " . MoneyHelper::format($result['total_net']) . "\n";
echo "KDV: " . MoneyHelper::format($result['total_vat']) . "\n";
echo "Brüt: " . MoneyHelper::format($result['total_gross']) . "\n";
```

### İndirimli Fatura

```php
$globalDiscount = MoneyHelper::toKurus("50.00"); // 50 TL

$result = TaxEngine::calculateInvoice($lineItems, 'net', $globalDiscount);
```

### KDV Dahil Fiyat Girişi

```php
// Kullanıcı 120 TL (KDV dahil) giriyor
$result = TaxEngine::calculateInvoice($lineItems, 'gross', 0);
// Sistem otomatik 100 TL net + 20 TL KDV hesaplar
```

---

## API Dokümantasyonu

### MoneyHelper

#### `toKurus($tl): int`
TL'yi kuruşa çevirir.

**Parametreler:**
- `$tl` (string|float): TL cinsinden tutar

**Döner:** Kuruş (integer)

**Örnek:**
```php
MoneyHelper::toKurus("123.45")  // 12345
MoneyHelper::toKurus("1.234,56") // 123456
```

#### `toTL($kurus): float`
Kuruşu TL'ye çevirir. **Sadece gösterim için!**

#### `format($kurus, $currency = 'TRY'): string`
Para formatlar.

**Örnek:**
```php
MoneyHelper::format(12345, 'TRY')  // "123,45 TRY"
```

### TaxEngine

#### `calculateVatFromNet($netKurus, $vatBasis): int`
Net fiyattan KDV hesaplar.

**Formül:** `vat = net * vatBasis / 10000`

**Parametreler:**
- `$netKurus` (int): Net fiyat (kuruş)
- `$vatBasis` (int): KDV oranı (basis points)

**Döner:** KDV tutarı (kuruş)

**Örnek:**
```php
TaxEngine::calculateVatFromNet(10000, 2000)  // 2000 (20 TL)
```

#### `calculateNetFromGross($grossKurus, $vatBasis): int`
KDV dahil fiyattan net hesaplar.

**Formül:** `net = gross * 10000 / (10000 + vatBasis)`

**Örnek:**
```php
TaxEngine::calculateNetFromGross(12000, 2000)  // 10000 (100 TL)
```

#### `calculateInvoice($lineItems, $inputType, $globalDiscount): array`
Fatura hesaplar.

**Parametreler:**
- `$lineItems` (array): Satır kalemleri
- `$inputType` (string): 'net' veya 'gross'
- `$globalDiscount` (int): Global indirim (kuruş)

**Döner:**
```php
[
    'lines' => [...],
    'total_net' => 25000,
    'total_vat' => 5000,
    'total_gross' => 30000,
    'global_discount' => 1000,
    'currency' => 'TRY'
]
```

### DiscountEngine

#### `distributeGlobalDiscount($lines, $globalDiscount, $totalNet): array`
Global indirimi satırlara dağıtır.

**Algoritma:**
1. Her satıra oransal dağıt
2. Fark varsa en büyük satıra telafi uygula

---

## Test

### Unit Testleri Çalıştırma

```bash
php tests/TaxEngineTest.php
```

### Test Senaryoları

1. **Basis Point Dönüşümü**
2. **KDV Dahil → Net**
3. **Net → KDV**
4. **Basit Fatura**
5. **Telafi Algoritması**
6. **İndirim Dağıtımı**
7. **Çoklu KDV Oranları**
8. **Edge Cases**

---

## Sorun Giderme

### Hata: "Overflow Exception"

**Neden:** Para değeri çok büyük (>92 trilyon TL)

**Çözüm:** Değerleri kontrol edin.

### Hata: "Invalid VAT Rate"

**Neden:** KDV oranı 0-10000 basis points aralığında değil

**Çözüm:** KDV oranını kontrol edin (0-100%)

### Telafi Tutarları Yanlış

**Neden:** Satır KDV'leri manuel değiştirilmiş

**Çözüm:** `TaxEngine::calculateInvoice()` kullanın, manuel hesaplama yapmayın

### Float Hatası

**Neden:** Eski decimal sütunlar kullanılıyor

**Çözüm:** Migration çalıştırın, `_kurus` sütunlarını kullanın

---

## Performans

- **Integer Arithmetic:** Float'a göre %30-40 daha hızlı
- **Batch Processing:** Transaction kullanımı
- **Index Optimization:** Veritabanı indeksleri
- **Caching:** KDV ayarı session'da cache'lenir

---

## Güvenlik

✅ Input validation  
✅ SQL injection koruması (prepared statements)  
✅ Overflow kontrolü  
✅ CSRF koruması  
✅ Audit trail  

---

## Lisans

Odjoo © 2024 - Tüm hakları saklıdır.

---

## Destek

Sorularınız için: support@odjoo.com

---

**🔥 Production-Ready | E-Fatura Uyumlu | Zero Float Error**
