feat(veri): CSV dışa ve içe aktarma (harcamalar, plan kalemleri, varlık işlemleri)

- Excel uyumlu CSV indirme
- İçe aktarma: önce deneme raporu (geçerli / zaten var / satır satır hata), onayla geçerli satırlar
- Sütunlar adla, esnek tutar/tarih yazımı, ; ve , ayırıcı, Windows-1254 desteği
- Varlıkta tarih sırasına göre eldekinden fazla satış denetimi
- Ayarlar sayfasında Veri bölümü

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-13 02:21:44 +03:00
parent 33f64a0459
commit 4d764689e2
21 changed files with 1961 additions and 5 deletions
+2 -1
View File
@@ -1,7 +1,7 @@
# 🧠 Proje Hafızası
## ▶️ Sıradaki Adım
**Faz 9 – Adım 3:** Uygulamanın kendi CSV'si (harcamalar, plan kalemleri, varlık işlemleri): dışa aktarma (backend ya da frontend; `lib/csv.ts` biçimi: BOM, `;`, `1250,50`, GG.AA.YYYY) + içe aktarma (önizleme → satır satır hata → geçerliler aktarılır; kategori/ödeme türü **adla** eşleşir; dönem tarihten bulunur, yazılamaz dönem → satır hatası). Adım 4 (ekstre) bunun üstüne kurulacak: ortak satır doğrulama/aktarma servisi tasarla.
**Faz 9 – Adım 4:** Banka / kredi kartı ekstresi içe aktarma (kullanıcı isteği; PHASES Faz 9 Adım 4). Önce tasarımı kullanıcıya sun: biçimler (CSV / Excel .xlsx — Excel için bağımlılık gerekir, gerekçe), sütun eşleştirme + banka profili (kaydedilir), yön (kart: harcama +; hesap: çıkış −, giriş = gelir?), taksit/iade, tekrar tespiti (tarih+tutar+açıklama), açıklamadan kategori önerisi (öğrenen kural, hane bazlı), **geçmiş (arşiv) dönemler** (yıl başından; plan yok → kapatma/devir zincirine etkisi; durum? `archived`?), aktarım `transfer.rs` + `csv_io.rs` üstüne. Karar gerektirenleri sor.
**Bekleyen (kullanıcıda):** Faz 5 – Adım 5 canlı yedek kurulumu (`docs/DEPLOY.md` §6.1–6.3) → çıktılar gelince Faz 5 ✅.
## 📌 Alınan Kararlar
@@ -136,3 +136,4 @@
### 2026-11-13 — Faz 9
- **Adım 1:** Rapor verileri. `/stats/periods` → `PeriodStat` artık `summary: budget::Summary` taşır; DTO'ya `income_total`, `fixed_expense_total`, `savings_goal`, `carryover_debt/surplus`, `realized_savings` (= review 4. soru) eklendi. `services/reports.rs` + `GET /reports/breakdown` (tek `$facet`: toplam, 4 grup sabit sırada (0 dahil), **tüm** kategoriler çoktan aza, ödeme türü (`$ifNull` → `null` = girilmemiş), ay `$substrBytes`; filtre dönem/tarih aralığı (dahil, başlangıç>bitiş 400)/grup/kategori/ödeme türü (`none`)). Bütçe sapması için yeni uç nokta yok (mevcut `/budget`). `tests/reports.rs` (1, kapsamlı) + stats testi genişledi. Mutasyon 2/2. Backend 155 test.
- **Adım 2:** Raporlar sayfası (`features/reports/`): `page.tsx` (filtre adreste: `donem`/`baslangic`/`bitis`/`grup`/`kategori`/`odeme` (`yok` = girilmemiş), dönem varsa tarih yok sayılır), `filters.tsx` (Kapsam: tüm zamanlar / dönem / tarih aralığı (yıl başı → bugün varsayılan), grup seçilince kategori listesi daralır, mobilde katlanır), `section.tsx` (`ReportSection`: `data-report`, CSV indir + bölüm yazdır; `ShareTable`: satır içi CSS pay çubukları — yazdırmada da görünür), `sections.tsx` (gruplar, ödeme türleri, **tüm** kategoriler, aylar = filtreli; bütçe sapması = seçili/açık/son dönem, grup + hafta; gelir–gider + birikim oranı = son 12 dönem; varlıklar), `charts.tsx` lazy (bar + çizgi). `lib/csv.ts` (BOM, `;`, CRLF, tırnaklama, `csvMoney` binliksiz), `lib/reports.ts` (`parseFilter`/`filterToParams`/`filterToQuery`, `describeFilter` → yazdırmada kapsam satırı, `savingsRate`, `deviation`, `formatMonth`), `lib/print.ts` (`installPrintTheme`: beforeprint'te koyu tema kaldırılır; `printSection`: `data-print-one` + `data-print-target`), index.css `@media print`, layout `print:hidden`. Kayıt değişince `['reports']` yenilenir. Frontend 121 test; e2e 34 kontrol (CSV baytları, yazdırma hedefi, tema, filtreler). Not: `Blob.text()` BOM'u siler → BOM'u baytlardan doğrula.
- **Adım 3:** CSV dışa/içe aktarma. Backend `services/csv_io.rs` (saf: yazma BOM/`;`/CRLF/`1250,50`/GG.AA.YYYY; okuma: BOM, `;`/`,`/sekme otomatik, tırnak, satır numarası, `norm` başlık eşleme (Türkçe İ/ı), `parse_money` (1.250,50 · 1250.50 · 1.000=bin), `parse_e6`, `parse_date_any`), `services/transfer.rs` (harcama/plan/varlık: dışa aktar; içe aktar `commit=false` deneme → rapor {total, valid, duplicates, imported, errors[(satır, neden)], preview}; tekrar sayacı `Existing` (dosyada 2, DB'de 1 → 1 eklenir); harcamada dönem tarihten, kapalı/yok → satır hatası, kategori adla (+grup), aynı ad 2 grupta → hata; plan `plan::create` ile; varlıkta tarih+dosya sırasına göre eldekinden fazla satış simülasyonu, yazma `asset::create_tx`). `Group::label()`. Rotalar `routes/transfer.rs` (`/export/*.csv`, `POST /import/{tür}` 5 MB). `tests/transfer.rs` (3) + csv_io birim (4); mutasyon 3/3. Frontend: Ayarlar → Veri (`features/settings/data-section.tsx`: indirme bağlantıları, içe aktarma: tür seç → dosya → deneme raporu → onay), `api.postCsv`, `lib/decode.ts` (UTF-8 fatal → Windows-1254), `lib/transfer.ts`. Backend 164, frontend 125 test; e2e 16 kontrol.