feat(transactions): ek bağlama, hesap ekstresi ve mutabakat servisi, 004 migration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 07:55:04 +03:00
parent 2e1f4d7929
commit 2e2e33233f
15 changed files with 1049 additions and 22 deletions
@@ -0,0 +1,20 @@
import { AttachmentModel } from "@/models/attachment";
import { ReconciliationModel } from "@/models/reconciliation";
import type { Migration } from "./types";
export const migration: Migration = {
name: "004-attachments-reconciliation",
description: "attachments ve reconciliations index'leri; işlemlerde mutabakat alanları",
async up(db) {
await AttachmentModel.createIndexes();
await ReconciliationModel.createIndexes();
const tx = db.collection("transactions");
// reconciledAt (hiç kullanılmadı) → hesap bazında reconciledAccountIds.
await tx.updateMany({ reconciledAt: { $exists: true } }, { $unset: { reconciledAt: "" } });
await tx.updateMany(
{ reconciledAccountIds: { $exists: false } },
{ $set: { reconciledAccountIds: [] } },
);
await tx.updateMany({ isAdjustment: { $exists: false } }, { $set: { isAdjustment: false } });
},
};
+2 -1
View File
@@ -3,10 +3,11 @@ 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 type { Migration } from "./types";
/** Sıralı migration listesi. Yeni migration: dosyayı ekle ve buraya sırayla ekle. */
export const MIGRATIONS: Migration[] = [m001, m002, m003];
export const MIGRATIONS: Migration[] = [m001, m002, m003, m004];
const COLLECTION = "migrations";
+13
View File
@@ -3,6 +3,7 @@ import { getAuth } from "@/lib/auth";
import { getDb } from "@/lib/db/mongo";
import { connectMongoose } from "@/lib/db/mongoose";
import { env } from "@/lib/env";
import { getStorage } from "@/lib/storage";
import { installDefaultCategories } from "@/features/categories/service";
import { AccountModel } from "@/models/account";
import { HouseholdModel } from "@/models/household";
@@ -53,6 +54,10 @@ const DOMAIN_COLLECTIONS = [
"auditLogs",
"categories",
"accounts",
"transactions",
"payees",
"attachments",
"reconciliations",
];
type AuthApi = ReturnType<typeof getAuth>["api"];
@@ -107,6 +112,14 @@ export async function runSeed({
};
if (reset) {
// Ek dosyaların diskteki kopyaları da silinsin (yetim dosya kalmasın).
const storage = getStorage();
for await (const a of db
.collection("attachments")
.find({}, { projection: { storageKey: 1, thumbKey: 1 } })) {
await storage.delete(String(a.storageKey));
if (a.thumbKey) await storage.delete(String(a.thumbKey));
}
for (const name of [...AUTH_COLLECTIONS, ...DOMAIN_COLLECTIONS]) {
await db.collection(name).deleteMany({});
}