# Apper Finance

## Kimlik
Çok kiracılı (multi-tenant) **finans ve stok yönetim sistemi**. Fatura/teklif/tahsilat yönetimi, banka hesap hareketleri, cari firma takibi, tekrarlayan hareketler, raporlama ve Apper **Posmanager** ile stok dağıtım entegrasyonu sunar. Mysoft e-Fatura/e-Arşiv gönderimi ve AI destekli fatura okuma (DeepSeek/Qwen Vision) içerir.

## Teknoloji Yığını
- **Backend**: Laravel **10.x**, PHP **^8.1** (ext-soap, ext-simplexml zorunlu)
- **Frontend**: TALL Stack — Tailwind CSS 3, Alpine.js, **Livewire 3**, Blade, Vite 5
- **Auth**: Laravel Jetstream (teams + 2FA) + Fortify + Sanctum
- **Paketler**: `apper/log-manager` (activity log; private VCS: `ugurkaragoz/apper-log-manager`), `barryvdh/laravel-dompdf` (PDF), `guzzlehttp/guzzle`
- **JS bağımlılıkları**: `@coasys/flux-ui`, `dinero.js`, `inputmask`
- **Test**: PHPUnit 10

## Komutlar
```bash
npm run dev                          # Vite dev server
npm run build                        # Frontend build
php artisan serve                    # Dev sunucusu
php artisan test                     # Testler
php artisan queue:work               # Queue worker (stok dağıtım job'ları için ŞART)
php artisan recurring:process-due    # Vadesi gelen tekrarlayan hareketler (scheduler: her gün 06:00)
php artisan optimize:clear
```

## Dizin Yapısı
```
app/
├── Actions/          # İş mantığı (StoreInvoiceAction, RecordActivity, RecordAiUsage, Mistral/ AI action'ları)
├── Console/Commands/ # recurring:process-due vb. artisan komutları
├── Http/Controllers/ # ~30 controller (HomeController dashboard sayfalarının hub'ı)
├── Jobs/             # SendStockAllocationJob (tries=3, backoff: 1dk/5dk/15dk)
├── Livewire/         # AiChat, BankAccountForm, BankAccountStatements, CreditBalance, Deals,
│                     # StockAllocationForm, TeamAddressForm
├── Models/           # Eloquent modeller + Scopes/ (global scope'lar)
├── Policies/         # Yetkilendirme politikaları
└── Services/         # Dış sistem entegrasyonları (aşağıda listeli)
docs/                # Proje dokümantasyonu (aşağıda listeli)
resources/views/     # Blade şablonları; domain klasörleri: invoice/, invoices/, receipts/,
                     # stock-allocations/, transactions/, companies/, integrations/, recurring-movements/
routes/web.php       # Tüm web rotaları (prefix gruplu)
routes/api.php       # Minimal (sanctum /user, company address)
tasks/               # Plan notları (recurring-movements-plan.md)
```

## Mimari

### 🏢 Çok Kiracılılık (Multi-Tenant)
Tüm ana modeller global scope ile team'e izole edilir — **bunu bypass etme**:

```php
// app/Models/Scopes/CurrentTeamScope.php (dosya adı: currentTeamScope.php)
static::addGlobalScope(new CurrentTeamScope);
// Sorguya otomatik ekler: where('current_team_id', auth()->user()->currentTeam->id)
```

- Yeni modelde `current_team_id`'yi `create()` verisine mutlaka ekle.
- **Dikkat**: Console/queue'da auth yokken scope no-op olur (tüm kayıtlar görünür) — komutlarda team'i manuela filtrele.
- `PosCompany` ve `PosWarehouse` ek olarak `selected_pos` global scope'u kullanır; `StockItem` ve `StockSupplier` `BulutadisyonScope` kullanır (remote entegrasyon filtresi).

### ⚠️ Uzak Veritabanı (mysql_remote / Posmanager)
Şu modeller **uzak sunucudadır** — `DB::connection('mysql_remote')` veya `Model::on('mysql_remote')` gerekir:

| Model | Tablo |
|---|---|
| `StockTransaction` | stock_transactions |
| `StockItem` | stock_items |
| `StockSupplier` | stock_suppliers |
| `FinancialDay` | financial_days |
| `PosCompany` | pos firmaları |
| `PosWarehouse` | pos depoları |

```php
// Transaction'ı da remote bağlantı üzerinde aç
DB::connection('mysql_remote')->beginTransaction();
try {
    // ...
    DB::connection('mysql_remote')->commit();
} catch (\Throwable $e) {
    DB::connection('mysql_remote')->rollBack();
    throw $e;
}
```

Bağlantı tanımı `config/database.php` → `mysql_remote` (env: `DB_HOST_REMOTE`, `DB_DATABASE_REMOTE`, ...). Kimlik bilgileri env'den gelmeli; config'e yeni secret gömme.

### Katmanlar
- **Actions**: Karmaşık iş akışları (`StoreInvoiceAction` fatura kaydetme; `RecordActivity`, `RecordAiUsage` loglama)
- **Services**: `PosmanagerService` (stok dağıtımı gönderimi), `MysoftEInvoiceService` (e-Fatura; `Integration` modeline bağlı token), `DeepSeekVisionService` (fatura görselinden veri çıkarma), `FinancialInsightService` (AI finansal içgörü), `ProductSyncService` (bulutadisyon → Product eşitleme), `TodoService`/`AgentService` (AI ajan görevleri), `DashboardGreetingService`
- **Jobs**: `SendStockAllocationJob` — Posmanager'a asenkron gönderim; başarısızlıkta `status=failed` + `error_message` kaydeder

### 📦 Stok Dağıtım Sistemi (Finance ↔ Posmanager)
Fatura kalemindeki ürün, hedef hesaplara (şube/depo) dağıtılır: `stock_allocations` (status: `planned → sent → completed`, `failed`). Detaylı dokümantasyon: `docs/STOCK_ALLOCATION_README.md` (ZORUNLU oku).

### 🧾 Invoice Modeli Notları
- `from_*` / `to_*` alanları adres anlık görüntüsüdür; `ex_*` alanları dövizli tutarlardır (`ex_rate` ile)
- E-fatura alanları Türkçe gelir: `belgeNo`, `ettn`, `gonderim_durumu`, `durum`, `yanit_durumu` vb.
- `SoftDeletes` + `Apper\LogManager\Loggable` kullanır

## Rotalar Haritası (`routes/web.php`)
Tümü `auth:sanctum` + Jetstream session + `verified` + `check.user.access` middleware'i arkasındadır (`CheckUserAccess`). Prefix grupları: `bank-accounts`, `companies`, `activities`, `reports`, `recurring-movements`, `offer`, `invoices`, `receipts`, `transactions`, `addresses`, `integrations` (bulutadisyon / sabee / e-files), `settings`, `stock-allocations`.

**Dikkat**: Eski rotalarda `destroy`/`store` GET ile yapılıyor (legacy). Yeni rotalarda doğru HTTP fiillerini kullan (DELETE, POST, PATCH).

## Kod Standartları
- **PSR-12**, Türkçe yorum/açıklama, İngilizce kod
- DB şema değişikliğinde **mutlaka migration** oluştur (bkz. "Migration Yönetimi" bölümü; mevcut tabloların çoğunun migration'ı yok — şemayı DB'den doğrula)
- Controller: `camelCase` metodlar; DB: çoğul `snake_case` tablolar
- Her request'te validation; her endpoint'te Policy/authorize kontrolü
- Blade'de kaçış: `{{ }}` kullan, asla `{!! !!}` (XSS)
- Para hesaplarında float kullanma — string tabanlı aritmetik/bcmath

## 🗄️ Migration Yönetimi (ÖNEMLİ)
Migration dosyaları ve `php artisan migrate` işlemleri **`admin.apper` ana yönetim projesinde** yapılır — **bu projede `php artisan migrate` ÇALIŞTIRMA**.

Bu projede bir özellik geliştirirken DB şeması değişikliği gerekiyorsa:
1. Migration dosyasını bu projede oluştur: `php artisan make:migration <ad>` (yalnızca dosya üretimi, migrate yok)
2. İçeriğini bu projede yaz (şema değişikliği, index, foreign key vb.)
3. Dosyayı kullanıcıya **bildir**: hangi tablo/alanda ne değişti, admin.apper projesinde migrate edilmesi gerektiği
4. `php artisan migrate`, `migrate:fresh`, `migrate:rollback`, `db:seed` gibi komutları burada asla çalıştırma; remote DB (`mysql_remote`) tablolarına migration uygulanmaz — remote şema değişikliği kullanıcıya bildirilir

## Test
- `tests/Feature`: AI chat, AI usage, stock allocation kontrolü + Jetstream auth testleri
- `tests/Unit`: hesaplamalar
- Remote DB kullanan kodda `DB::connection('mysql_remote')` fake/mock'la; testlerde gerçek remote DB'ye yazma

## Harici Dokümanlar (konuyla ilgiliyse oku)
- `@docs/STOCK_ALLOCATION_README.md` — stok dağıtım sistemi (tam dokümantasyon)
- `@docs/deepseek/configure.md` — DeepSeek API kurulumu
- `@docs/qwen/configure.md`, `@docs/qwen/qwen-3.5-flash_image-to-text.md` — Qwen görsel-anlama
- `@.github/copilot-instructions.md` — ayrıntılı kod standartları ve örnekler
- `@.github/copilot-agents/README.md` — financial / livewire / security / testing uzman ajan tanımları
- `@.github/copilot-todo.md` — proje görev listesi
- `@tasks/recurring-movements-plan.md` — tekrarlayan hareketler planı

## ⚠️ Yaygın Tuzaklar
1. `docs/database-schema.md` ve `docs/api-standards.md` **yok** — bu referanslara güvenme
2. Uzak tablolara yerel bağlantıdan yazma → her zaman `mysql_remote`
3. Queue worker çalışmıyorsa stok dağıtım job'ları işlenmez
4. `resources/views/bank-acconts/` (typo) eski klasördür; yeni view'lar için doğru isimlendir
5. Invoice `number` üretimi `count(Invoice::all())`'a dayanır (`StoreInvoiceAction`) — yarış koşullarına dikkat
6. Global scope'u `withoutGlobalScopes()` ile atlamak team izolasyonunu bozar
7. Bu projede `php artisan migrate` çalıştırmak → migration'lar `admin.apper` ana projesinde koşulur; burada yalnızca dosya üret (bkz. "Migration Yönetimi")