# Fatura Tutar Kancaları

https://dev.wisecp.com/tr/fatura-tutar-kancalari

Faturadaki rakamlara dokunan on üç kanca: kalemler, toplamlar, gecikme ücreti, yenileme fiyatı ve resmileştirme.

## Genel Bakış

Bu kancalar müşterinin **ödeyeceği tutarı** belirler. Hepsi referansla çalışır ve yazdığınız değer doğrudan faturaya girer; hesap hatası burada **paraya dönüşür**.

Son iki kanca farklıdır: resmileştirme, faturayı **yasal bir belgeye** çevirir. O noktadan sonra tutar değiştirilemez, fatura silinemez ve numarası sabitlenir.

## Referans

### Fatura toplamlarını değiştirme

filterinvoice.totals

`Invoices` kaydedilmeden önce

Toplamlar hesaplandıktan sonra, faturaya yazılmadan önce çalışır.

Parametreler 3

$totalsarrayrefYazılacak toplamlar: `subtotal`, `tax`, `additional_tax`, `pmethod_commission`, `total`, `discounts`. Yalnız birini değiştirmek toplamı **tutarsız** bırakır; ara toplama dokunduysanız genel toplamı da düzeltin.

$invoicearrayFatura satırı: vergi oranı, resmileşme durumu, para birimi, komisyon oranı. Değiştirilemez bağlam.

$itemsarrayHesaplamada kullanılan kalemler. Değiştirilemez bağlam.

Dönüş 1

voidDeğer **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:invoice.totals', 10, function (&$totals, $invoice, $items) {
    // Bir alani degistirdiyseniz TOPLAMI da elden gecirin.
    if (Acme::roundUp($invoice)) {
        $totals['total'] = ceil((float) $totals['total']);
    }
});
```

### Fatura indirimlerini değiştirme

filterinvoice.items

`AdminInvoices` indirim JSON'u

Fatura düzenlenirken indirimler kaydedilmeden önce çalışır.

Parametreler 4

$idintDüzenlenen faturanın kimliği.

$invDiscountsarrayrefKaydedilecek indirimler; kalem bazlı özel indirimler de içindedir. Ad benzese de bu **kalem listesi değil**, indirim yapısıdır.

$pendingCustomDiscountsarrayKalem kimliğine göre gruplanmış özel indirimler.

$invoicearrayMevcut fatura satırı.

Dönüş 1

voidDeğer **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:invoice.items', 10,
    function ($id, &$invDiscounts, $pendingCustomDiscounts, $invoice) {
        // Ad yaniltici: bu KALEM listesi degil, indirim yapisidir.
        Acme::capDiscounts($invDiscounts, (float) ($invoice['subtotal'] ?? 0));
    });
```

### Gecikme ücretini değiştirme

filterinvoice.late_fee_amount

`cronjobs/InvoiceLateFee` sonra yuvarlanır

Gecikme ücreti hesaplandıktan sonra, faturaya kalem olarak eklenmeden önce çalışır.

Parametreler 3

$feefloatrefHam gecikme ücreti, faturanın para biriminde. Filtreden sonra **yeniden yuvarlanır**, o yüzden burada kuruş hesabı yapmanız gerekmez.

$invoicearrayFatura satırı: ara toplam, para birimi, sahip.

$cyclestringÜcret döngüsü: bir kez ya da günlük. Günlük döngüde bu kanca **her gün** çalışır.

Dönüş 1

voidDeğer **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:invoice.late_fee_amount', 10, function (&$fee, $invoice, $cycle) {
    // Gunluk donguda her gun calisir: tavani asmayin.
    $cap = (float) ($invoice['subtotal'] ?? 0) * 0.2;
    if ($fee > $cap) $fee = $cap;
});
```

### Gecikme ücretinin eklendiğini izleme

actioninvoice.late_fee_applied

`cronjobs/InvoiceLateFee` kalem oluştu

Gecikme ücreti faturaya kalem olarak eklendikten sonra çalışır.

Parametreler 4

$invoice_idintÜcret eklenen fatura.

$fee_amountfloatEklenen tutar — **filtreden sonraki nihai** değer.

$fee_typestring`percentage` ya da `fixed`.

$item_idintOluşan fatura kaleminin kimliği.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:invoice.late_fee_applied', 10,
    function ($invoice_id, $fee_amount, $fee_type, $item_id) {
        // Musteriye fatura buyudugunu haber verin; sessiz artis sikayete doner.
        Notify::lateFee($invoice_id, (float) $fee_amount);
    });
```

### Yenileme fiyatını değiştirme

filterinvoice.renewal_amount

`Invoices` birim fiyat

Bir hizmetin yenileme fiyatı çözüldükten sonra çalışır.

Parametreler 1

$resultarrayrefFiyat sonucu: `amount` (**birim** fiyat), `quantity`, `currency`, `taxexempt`, `additional_taxes`, `discounts`, `pricing_source`, `period_time`. Tutar **adet başınadır**; toplam sonradan çarpılır.

Dönüş 1

voidDeğer **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:invoice.renewal_amount', 10, function (&$result) {
    // amount BIRIM fiyattir: adetle carpimi cekirdek yapar.
    if (($result['pricing_source'] ?? '') === 'locked') return;

    $result['amount'] = Acme::loyaltyPrice((float) $result['amount']);
});
```

### Yenileme açıklamasını değiştirme

filterinvoice.renewal_description

`Invoices` faturada görünür

Yenileme kaleminin açıklaması hazırlandıktan sonra çalışır.

Parametreler 1

$descriptionstringrefKalem açıklaması. Müşterinin faturada gördüğü metindir; müşterinin dilinde yazın.

Dönüş 1

voidDeğer **referansla** değişir; dönüş kullanılmaz.

Dinleyici PHP

```php
Hook::add('filter:invoice.renewal_description', 10, function (&$description) {
    $description .= ' — ' . Acme::periodNote();
});
```

### Resmileştirmeyi durdurma

gateinvoice.formalize

`AdminInvoices` geri dönüşü yok

Fatura resmileştirilmeden önce çalışır. Bu adımdan sonra fatura **değiştirilemez ve silinemez**.

Parametreler 2

$invoicearrayResmileştirilecek fatura.

$user_idintİşlemi yapan kişinin kimliği.

Dönüş 1

stringBoş olmayan bir string resmileştirmeyi **durdurur**; metin hata olarak fırlatılır.

Dinleyici PHP

```php
Hook::add('gate:invoice.formalize', 10, function ($invoice, $user_id) {
    // Resmilesme geri alinamaz: eksik vergi bilgisiyle yapilmasin.
    if (!Acme::taxDetailsComplete($invoice))
        return 'Vergi bilgileri tamamlanmadan fatura resmilestirilmez.';

    return null;
});
```

### Resmileşmeyi izleme

actioninvoice.formalized

`AdminInvoices` taze okunmuş

Fatura resmileştikten sonra çalışır.

Parametreler 2

$invoicearrayResmileşme işaretiyle **yeniden okunmuş** fatura; oluşturulmuşsa belge dosyası da içindedir.

$user_idintİşlemi yapan kişinin kimliği.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:invoice.formalized', 10, function ($invoice, $user_id) {
    // Artik yasal belge: muhasebeye buradan gonderin, once degil.
    Accounting::submit($invoice);
});
```

### Liste özet kartlarını değiştirme

filterinvoice.list_stats

`admin/invoices` bağla geçer

Fatura listesinin üstündeki özet kartları hesaplandıktan sonra çalışır. Değiştirdiğiniz değerler hem karta hem de kart alanına ekleme yapan görsel kancaya geçer.

Parametreler 2

$initial_statsarraybağlaKart verileri: ödenmemiş, ödenmiş ve vadesi geçmiş; her biri biçimlenmiş tutar ve adet taşır.

$stats_cardsarrayKart yapılandırması: tip ve dönem.

Dönüş 1

voidDönüş yoksayılır; dizinin üzerine yazarsınız.

Dinleyici PHP

```php
Hook::add('filter:invoice.list_stats', 10, function (&$initial_stats, $stats_cards) {
    // Bayi faturalarini ozetin disinda tutun.
    $initial_stats['unpaid']['formatted'] = Acme::excludeResellers($initial_stats['unpaid']);
});
```

### Fatura belgesinin yazı tipini değiştirme

filterinvoice.pdf_font

`Invoices::create_pdf` nesne üzerinden

Fatura belgesi oluşturulurken çalışır. Latin dışı alfabelerde varsayılan yazı tipi harfleri basamaz: doğru yazı tipini burada verirsiniz.

Parametreler 2

$pdfobjectBelge oluşturucu. Nesne olduğu için bağla işareti olmadan da değişir: metodunu çağırmanız yeterlidir.

$invoicearrayFatura kaydı. Müşterinin kayıtlı dili içindedir; kopyadır, değiştirmenin etkisi yoktur.

Dönüş 1

voidDönüş yoksayılır. Değişikliği nesnenin metodunu çağırarak yaparsınız.

Dinleyici PHP

```php
Hook::add('filter:invoice.pdf_font', 10, function ($pdf, $invoice) {
    // Latin disi alfabede varsayilan yazi tipi harfleri basamaz.
    if (($invoice['user_data']['lang'] ?? '') === 'ru') $pdf->setDefaultFont('dejavusans');
});
```

### Fatura belgesine blok ekleme

filterinvoice.document_blocks

`Invoices::document_blocks` belge ve fatura sayfası

Fatura belgesi oluşturulurken ve müşteri fatura sayfasını açarken çalışır. Başlığı ve açıklaması olan bir görseli burada eklersiniz: e-fatura ya da ödeme QR kodu, doğrulama damgası.

Parametreler 3

$blocksarrayrefBoş başlar. Her blok için `image`, `title` ve `description` taşıyan bir öğe eklersiniz. Görsel zorunludur: PNG, JPEG ya da GIF data URI'si veya sunucudaki böyle bir dosyanın yolu. Web adresi reddedilir. En çok dört blok görünür, metinleri düz metin olarak görünür.

$invoicearrayFatura kaydı: numara, toplam, para birimi ve müşteri bilgileri. Değiştiremeyeceğiniz bağlam.

$surfacestringSunucunun oluşturduğu belge için `pdf` (fatura e-postasının eki, panelden indirme), müşterinin fatura sayfası için `screen`. Müşterinin kendi indirdiği PDF o sayfanın görüntüsüdür; `screen` için eklenen blok ona da girer.

Dönüş 1

voidListe **referansla** değişir; dönüş okunmaz. Görseli okunamayan blok düşer ve belge yine oluşturulur; sebebi hata kaydına yazılır.

Dinleyici PHP

```php
Hook::add('filter:invoice.document_blocks', 10, function (&$blocks, &$invoice, &$surface) {
    // QR gorselini burada uretin; web adresi indirilmez.
    $png = Acme::invoiceQr($invoice);
    $blocks[] = [
        'image'       => 'data:image/png;base64,' . base64_encode($png),
        'title'       => 'E-fatura QR kodu',
        'description' => 'Faturayı doğrulamak için okutun.',
    ];
});
```

### Ödeme yöntemi logosu ekleme

registerinvoice.module_logos

`templates/admin` tek URL döner

Fatura ekranında ödeme yöntemi rozetleri gösterilirken çalışır. Kendi yönteminizin logosunu buraya eklersiniz.

Parametreler 0

—Parametre almaz.

Dönüş 1

string|null**Tek bir adres** döndürürsünüz, HTML değil: şablon onu bir görsele yerleştirir. Logo göstermek istemiyorsanız `null` döndürün. Boş metin, sıfır ve yanlış değerler zaten elenir.

Dinleyici PHP

```php
Hook::add('register:invoice.module_logos', 10, function () {
    // HTML degil, tek bir adres dondurun.
    return Acme::assetUrl('acme-pay.svg');
});
```

### Müşterinin kupon uygulamasını izleme

actioninvoice.coupon_applied_by_client

`ClientInvoices` müşteri uyguladı

Müşteri kendi faturasına kupon uyguladıktan sonra çalışır. İndirim çoktan işlenmiştir.

Parametreler 4

$uidintKuponu uygulayan müşteri.

$idintFatura kimliği. Faturanın kendisi kasten geçilmez: kanca çalıştığında tutarlar değişmiştir, elinizdeki kopya bayat olurdu. Gerekiyorsa taze okuyun.

$couponarrayKupon kaydı. Tutar alanı uygulama sırasında değişmiş olabilir.

$couponCtxarrayUygulamanın sonucu: indirim tutarı, para birimi ve etkilenen kalemler.

Dönüş 1

voidDönüş yoksayılır.

Dinleyici PHP

```php
Hook::add('action:invoice.coupon_applied_by_client', 10,
    function ($uid, $id, $coupon, $couponCtx) {
        // Fatura satiri kasten gecilmez: gerekiyorsa taze okuyun.
        Acme::trackDiscount($uid, $coupon['code'] ?? '', (float) ($couponCtx['discount'] ?? 0));
    });
```

## Tuzaklar

> **Bir rakamı değiştirmek diğerlerini düzeltmez**
> 
> Toplamlar filtresinde ara toplamı değiştirip genel toplamı olduğu gibi bırakmak, faturayı **kendi içinde tutarsız** yapar: müşteri bir rakam görür, ödeme başka bir rakamı ister. Bir alana dokunduysanız **bağlı olanları da** elden geçirin.

> **İndirim filtresinin adı kalem listesi sanılır**
> 
> Adı kalemleri çağrıştırsa da bu filtre **indirim yapısını** verir. Kalem listesi bekleyen bir dinleyici tanımadığı bir dizi bulur ve sessizce yanlış yere yazar. İkinci parametrenin ne olduğunu **kaydından** doğrulayın.

> **Günlük gecikme ücreti her gün çalışır**
> 
> Ücret döngüsü günlükse filtre ve olay **her gün yeniden** çalışır. Tavan koymayan bir kural, ödenmemiş bir faturayı haftalar içinde **ödenemez** hâle getirir. Bildirim gönderiyorsanız da her gün göndermemeye dikkat edin.

> **Resmileşme bir noktadır, geri dönüşü yoktur**
> 
> Resmileşen fatura **silinemez ve tutarı değiştirilemez**. Muhasebeye gönderme, numara ayırma ve arşivleme gibi işler **resmileşme olayına** yazılır; daha erken yazılan iş, sonradan iptal edilen bir faturayı yasal kayıt sanar.

## İlgili Makaleler

- [Fatura Yaşam Döngüsü Kancaları](https://dev.wisecp.com/tr/fatura-yasam-dongusu-kancalari)
- [Ödeme Kancaları](https://dev.wisecp.com/tr/odeme-kancalari)
- [Hizmet Yenileme Kancaları](https://dev.wisecp.com/tr/hizmet-yenileme-kancalari)
