feat(yedek): JSON tam hane yedeği backend (önizleme, geri yükleme, geri dönüş noktaları)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,7 @@ Renkler ve ikonlar frontend tasarım token'larında.
|
||||
budget_split_pct: { needs: 50, wants: 30, culture: 10, unexpected: 10 },
|
||||
budget_suggestion: "previous" | "avg3" | "default" // varsayılan öneri yöntemi
|
||||
},
|
||||
last_backup_at, // son JSON dışa aktarma ("son yedek X gün önce")
|
||||
created_at, updated_at, deleted_at, version }
|
||||
```
|
||||
- `household_id` = `_id` (ortak `scope()` filtresi tüm koleksiyonlarda aynı çalışsın diye).
|
||||
@@ -202,6 +203,30 @@ Renkler ve ikonlar frontend tasarım token'larında.
|
||||
- Otomatik kurlar gün başına tek kayıt (kod × kaynak × gün; aynı gün yeniden çekilince güncellenir) → günlük geçmiş birikir. TCMB `rate_date` = bülten tarihi; altın = Türkiye'de bugün.
|
||||
- Altın: xaus.com gram (saf) USD × TCMB USD alış; çeyrek/yarım/tam = has gram (1,603 / 3,206 / 6,412) × gram, ons = 31,1034768 gr. İşçilik payı yok → gerekirse manuel.
|
||||
|
||||
### 3.14a `restore_points` — JSON geri yüklemeden önceki durum ("geri al")
|
||||
```js
|
||||
{ _id, household_id, created_at, created_by,
|
||||
reason: "before_restore" | "before_undo",
|
||||
counts: { periods: 3, entries: 412, ... }, // o anki silinmemiş kayıt sayıları
|
||||
size, // sıkıştırılmış bayt
|
||||
data: BinData } // gzip(JSON yedek dosyası)
|
||||
```
|
||||
- Her geri yükleme / geri alma öncesinde aynı transaction içinde yazılır. Son **3** nokta, en fazla **30 gün** (`backup::prune`). Hane verisi değil → yedeğe girmez.
|
||||
|
||||
### 3.14b JSON yedek dosyası (`services/backup.rs`)
|
||||
```js
|
||||
{ "format": "kakeibo-backup", "format_version": 1, "schema_version": 3, "app_version": "0.1.0",
|
||||
"exported_at": "2026-11-13T17:22:00Z",
|
||||
"household": { "id", "name", "settings" },
|
||||
"counts": { "entries": 412, ... }, // silinmemiş
|
||||
"checksum": "sha256:…", // household + data, anahtarlar sıralı
|
||||
"data": { "periods": [ {…}, … ], "entries": [ … ], … } } // her kayıt bir satır
|
||||
```
|
||||
- İçerik: dönem, plan kalemi, bütçe, harcama, devir, not, kategori, ödeme türü, varlık, varlık işlemi, elle girilen kur, ekstre kuralı — **silinmiş işaretliler dahil** (referanslar kopmasın, "geri al" birebir olsun). Kullanıcı, şifre, oturum, davet, otomatik kur **yok**.
|
||||
- Değerler: UUID `{"$uuid": "…"}`, zaman `{"$date": "…"}`, tam sayılar `i64` (`version`, `sort_order` ve ayarlar `i32`).
|
||||
- Geri yükleme = **tam değiştirme** (birleştirme yok), tek transaction. Aynı hane → kimlikler korunur; başka hane → tüm `_id`'ler yeniden üretilir, `*_id` referansları çevrilir, `household_id` hedef hane, `*_by` hanede yoksa geri yükleyen kişi. Hane adı yalnız aynı hanede geri gelir; ayarlar her zaman.
|
||||
- Sürüm: `format_version`/`schema_version` daha yeniyse reddedilir; eskiyse hane düzeyi yükseltmeler uygulanır (v<2 → varsayılan varlıklar).
|
||||
|
||||
### 3.15 `schema_migrations`
|
||||
```js
|
||||
{ _id: 1 /* sürüm numarası */, name: "initial", applied_at }
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
# 🧠 Proje Hafızası
|
||||
|
||||
## ▶️ Sıradaki Adım
|
||||
**Faz 9 – Adım 5a:** JSON yedeği backend. Tasarım kullanıcıya sunuldu ve onaylandı ("5a'dan devam"): `kakeibo-yedek-<hane>-<tarih>.json` (format/şema sürümü, zaman, hane, sayılar, SHA-256), içerik hane verisi (kullanıcı/şifre/davet/otomatik kur/silinmiş yok), dışa aktarma her üye, geri yükleme yalnız sahip; önizleme → tam değiştirme (birleştirme yok) tek transaction; geri yüklemeden önce sıkıştırılmış geri dönüş noktası (`flate2`), son 3 / 30 gün, "geri al" da nokta oluşturur; aynı hane → kimlikler korunur, başka hane → yeniden üretilir + iç referanslar çevrilir, `created_by` yoksa geri yükleyen; eski biçim yükseltilir, yeni biçim reddedilir; 20 MB. 5b: arayüz + "son yedek X gün önce" hatırlatması.
|
||||
**Faz 9 – Adım 5b:** JSON yedeği arayüzü (Ayarlar → Veri): "Yedeği indir" (son yedek X gün önce / hiç alınmadı hatırlatması), sahip için "Yedekten geri yükle" → dosya seç → önizleme (kaynak hane, tarih, kayıt sayıları yedek/şimdi, tarih aralığı, uyarılar) → onay kutusu → geri yükle → sonuç + "Geri al"; geri dönüş noktaları listesi (tarih, neden, kayıt sayısı, "Bu duruma dön" onaylı). Tipler hazır: `BackupStatus`, `BackupPreview`, `BackupCount`, `RestorePoint`, `RestoreResult`. Gövde: dosya metni (`api.postCsv` benzeri, `application/json`). Sonra Adım 6 aylık rapor.
|
||||
**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
|
||||
@@ -142,3 +142,4 @@
|
||||
- **Adım 4a:** Ekstre backend. `PeriodStatus::Archived` (yazılabilir; kapatılmaz 409; devir zincirinde atlanır: `period::create` önceki, `closing::next_period`, reopen engeli; `budget::previous_closed` kapalı+arşiv), `period::create_archive`. `services/bank_import.rs`: `fold` (Türkçe → ASCII; **"İ".to_lowercase() = i + U+0307** düzeltildi), `rule_key` (ilk 2 anlamlı kelime), `import_key`, `default_kind` (ödeme/virman → yoksay; kartta giriş → iade, hesapta → gelir), `target` (içeren yazılabilir dönem / takvim ayı arşivi (kırpılmış) / gelecek-kapalı engel), `preview`, `commit` (arşivleri açar, harcama/iade insert_many + `import_key`, gelir `plan::create` + `import_key`, kurallar upsert `import_rules`). Entry update: iade eksi kalır. Rotalar `routes/bank_import.rs` (`/bank-import/preview|commit`, 5 MB). `tests/bank_import.rs` (3, devir zinciri dahil); mutasyon 5/5. Frontend: `archived` durum metni, Değerlendirme'de arşiv bilgisi, kapatma sihirbazı arşivi reddeder. Backend 177 test.
|
||||
- **Adım 4b:** Ekstre arayüzü `/ayarlar/ekstre` (`features/statement/`: `page.tsx` Dosya → Eşleştir (başlık satırı otomatik `detectHeaderRow`, sütun tahmini `guessMapping`, kaynak kart/hesap → tutar modu, Borç/Alacak, ödeme türü, profil adı → localStorage `kakeibo.statement.profiles`, ad ile eşleşir; önizlemede tarih yorumlanmış) ; `review.tsx` (tür+kategori, değişiklik aynı `ruleKey`'li elle değiştirilmemiş satırlara yayılır + bildirim, filtreler, sayfalama 50, telefonda kart/masaüstünde sütunlu liste, atlanacaklar soluk, arşiv bildirimi, kategori eksikse aktarma kapalı, sonuçta hata satırları tarih+açıklama ile)). `lib/statement.ts` (Excel seri tarih, `parseAmount` TR/EN/parantez/sondaki eksi, `normalize`, `fold`/`ruleKey` = backend, profiller), `lib/read-sheet.ts` (SheetJS lazy 160 KB gz, `blankrows: true` → satır no Excel ile aynı; CSV kendi ayrıştırıcı + `decodeText`), `lib/bank-import.ts`. Backend: kural önerisine **ilk kelime yedeği** (`suggest`, genel kelimeler hariç). SheetJS yerel paket (`frontend/vendor`, Dockerfile kopyalar; Docker web aşaması doğrulandı). Defter: iade satırı "İade" etiketi, düzenlemede artı gösterilip eksi kaydedilir. Frontend 134, backend 178 test; e2e 25 kontrol.
|
||||
- **Hafta düzeltmesi (2026-11-13):** `calendar::weeks` yeni kural (testler: Kasım/Aralık/Şubat/artık yıl, ay ortası dönem, 13/14/62 gün). Bütçe/defter/değerlendirme entegrasyon testleri yeni sınırlara göre güncellendi (backend 178). Frontend: `LedgerView` haftayı `useState`'te tutar, `parseWeekParam` kaldırıldı, dönem kısalırsa son haftaya düşer; `budget-preview`/`ledger` testleri yeni Aralık (8,7,7,9) ile (133). E2E 9 kontrol (8091, DB silindi). Dev verisinde elle haftalık bütçe yoktu → taşıma gerekmedi; canlıda varsa eşleşmeyen eski hafta yok sayılır (aylık tutar korunur).
|
||||
- **Faz 9 – Adım 5a (2026-11-13):** `services/backup.rs` + `routes/backup.rs` (`/backup/download|status|preview|restore`, `/backup/restore-points/{id}/restore`; preview/restore/undo **sahip**, 20 MB). Biçim ham BSON belgeleri üzerinden (modeller eksik alanlı olduğu için tür tabanlı değil): `$uuid`/`$date`, `INT32_KEYS` (version, sort_order) + ayarlar i32 (`small_ints`), SHA-256 kanonik (sıralı anahtar) → yeniden biçimlendirilmiş dosya geçerli, değiştirilmiş reddedilir. **Silinmiş kayıtlar dahil** (tasarımdan sapma: referans bütünlüğü + birebir geri al). Migration v3 `restore_points` (transaction içinde ilk yazım için) + indeks. `flate2`, `sha2` doğrudan eklendi (zaten bağımlılık ağacında). Testler: 4 birim + 3 entegrasyon (aynı hane + geri al zinciri + 3 nokta sınırı, başka haneye iki kez kopya, bozuk/yabancı/yeni sürüm dosya, üye 403, başka hane 404). 3 bilinçli bozma yakalandı. Backend 190 test.
|
||||
|
||||
+1
-1
@@ -83,5 +83,5 @@
|
||||
- ✅ 2. Frontend: Raporlar sayfası — filtreler (adreste), gelir–gider çubuk grafiği, kategori kırılımı (tablo + grafik), bütçe sapması, ödeme türü dağılımı, birikim oranı trendi, varlık performansı; her rapor CSV (UTF-8 BOM, `;`) + yazdır
|
||||
- ✅ 3. CSV dışa/içe aktarma (uygulamanın kendi biçimi): harcamalar, plan kalemleri, varlık işlemleri; içe aktarmada önizleme + satır satır hata raporu
|
||||
- ✅ 4. **Banka / kredi kartı ekstresi içe aktarma** — 4a backend (arşiv dönemleri, iade, gelir, yoksay, tekrar, öğrenen kurallar) + 4b arayüz (`/ayarlar/ekstre`: Excel/CSV, sütun eşleştirme + profil, gözden geçirme)
|
||||
- ⏳ 5. JSON tam hane yedeği: sürümlü dışa aktarma; geri yüklemede önizleme + onay + sunucuda otomatik geri dönüş noktası ("geri yüklemeyi geri al"); başka haneden taşıma
|
||||
- 🔄 5. JSON tam hane yedeği — ✅ 5a backend (sürümlü dosya + SHA-256, önizleme, tam değiştirme tek transaction, geri dönüş noktaları + "geri al", başka haneye kimlik çevirerek taşıma) · ⏳ 5b arayüz (Ayarlar → Veri)
|
||||
- ⏳ 6. Aylık değerlendirme çıktısı: `templates/monthly_report.md` (Claude tasarlar — müşteri gözüyle: ne yaptım, ne iyi/kötü gitti, ne yapmalıydım, gelecek ay önerileri) → Markdown + yazdırılabilir/PDF
|
||||
|
||||
Reference in New Issue
Block a user