ebcdf3f741
- Kredi Kartı / Maaş Hesabı sayfaları ayrıştırılır; ekstre toplamı ve bakiye zinciri kontrolü, taksit planı, iade = gelir, kart ödemesi / ATM / hesaplar arası = transfer, KMH ve ücretler = banka maliyeti - Taslak parti (importBatches), hesap rolleri ve önerilen hesaplar, satır düzenleme (aynı açıklamalılara toplu), tek transaction'da işleme, parmak iziyle tekrar engeli ve toplu geri alma - Migration 017-imports (geri alınabilir), denetim kayıtları Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import { getDb } from "@/lib/db/mongo";
|
||
import { connectMongoose } from "@/lib/db/mongoose";
|
||
import { migration as m001 } from "./001-initial-indexes";
|
||
import { migration as m002 } from "./002-accounts-categories";
|
||
import { migration as m003 } from "./003-transactions";
|
||
import { migration as m004 } from "./004-attachments-reconciliation";
|
||
import { migration as m005 } from "./005-recurring";
|
||
import { migration as m006 } from "./006-card-statements";
|
||
import { migration as m007 } from "./007-contacts";
|
||
import { migration as m008 } from "./008-in-kind";
|
||
import { migration as m009 } from "./009-assets";
|
||
import { migration as m010 } from "./010-budgets";
|
||
import { migration as m011 } from "./011-stock";
|
||
import { migration as m012 } from "./012-stock-counts";
|
||
import { migration as m013 } from "./013-stores-products";
|
||
import { migration as m014 } from "./014-product-prices";
|
||
import { migration as m015 } from "./015-shopping-lists";
|
||
import { migration as m016 } from "./016-kakeibo-groups";
|
||
import { migration as m017 } from "./017-imports";
|
||
import type { Migration } from "./types";
|
||
|
||
/** Sıralı migration listesi. Yeni migration: dosyayı ekle ve buraya sırayla ekle. */
|
||
export const MIGRATIONS: Migration[] = [
|
||
m001,
|
||
m002,
|
||
m003,
|
||
m004,
|
||
m005,
|
||
m006,
|
||
m007,
|
||
m008,
|
||
m009,
|
||
m010,
|
||
m011,
|
||
m012,
|
||
m013,
|
||
m014,
|
||
m015,
|
||
m016,
|
||
m017,
|
||
];
|
||
|
||
const COLLECTION = "migrations";
|
||
|
||
/**
|
||
* Uygulanmamış migration'ları sırayla çalıştırır; her biri bir kez (`migrations` koleksiyonu).
|
||
* Aynı anda iki çalıştırma olursa benzersiz `name` index'i ikinci kaydı reddeder.
|
||
*/
|
||
export async function runMigrations(log: (line: string) => void = console.log): Promise<string[]> {
|
||
const db = getDb();
|
||
await connectMongoose();
|
||
const col = db.collection<{ name: string; appliedAt: Date; durationMs: number }>(COLLECTION);
|
||
await col.createIndex({ name: 1 }, { unique: true });
|
||
const applied = new Set(
|
||
(await col.find({}, { projection: { name: 1 } }).toArray()).map((d) => d.name),
|
||
);
|
||
|
||
const ran: string[] = [];
|
||
for (const m of MIGRATIONS) {
|
||
if (applied.has(m.name)) continue;
|
||
const started = Date.now();
|
||
await m.up(db);
|
||
await col.insertOne({ name: m.name, appliedAt: new Date(), durationMs: Date.now() - started });
|
||
ran.push(m.name);
|
||
log(`✓ Migration: ${m.name} — ${m.description}`);
|
||
}
|
||
if (!ran.length) log("• Bekleyen migration yok.");
|
||
return ran;
|
||
}
|
||
|
||
/**
|
||
* Bir migration'ı geri alır (yalnızca `down` tanımlıysa) ve kaydını siler; bir sonraki
|
||
* `runMigrations` onu yeniden uygular. Kullanım: npm run migrate -- --down 016-kakeibo-groups
|
||
*/
|
||
export async function revertMigration(
|
||
name: string,
|
||
log: (line: string) => void = console.log,
|
||
): Promise<void> {
|
||
const m = MIGRATIONS.find((x) => x.name === name);
|
||
if (!m) throw new Error(`Migration bulunamadı: ${name}`);
|
||
if (!m.down) throw new Error(`${name} geri alınamaz (down tanımlı değil).`);
|
||
const db = getDb();
|
||
await connectMongoose();
|
||
const col = db.collection<{ name: string }>(COLLECTION);
|
||
if (!(await col.findOne({ name }))) throw new Error(`${name} uygulanmamış.`);
|
||
await m.down(db);
|
||
await col.deleteOne({ name });
|
||
log(`↩ Geri alındı: ${name}`);
|
||
}
|