feat(seed): varsayılan kategoriler, örnek hesaplar ve 002 migration

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 02:57:58 +03:00
parent d2aa9d8ae2
commit 0558d92203
6 changed files with 202 additions and 10 deletions
+71 -5
View File
@@ -3,11 +3,19 @@ import { getAuth } from "@/lib/auth";
import { getDb } from "@/lib/db/mongo";
import { connectMongoose } from "@/lib/db/mongoose";
import { env } from "@/lib/env";
import { installDefaultCategories } from "@/features/categories/service";
import { AccountModel } from "@/models/account";
import { HouseholdModel } from "@/models/household";
import { HouseholdMemberModel } from "@/models/household-member";
import { storedEmail } from "@/shared/account-email";
import { runMigrations } from "../migrations";
import { ADMIN_USERNAME, SEED_HOUSEHOLDS, SEED_USERS, type SeedUser } from "./fixtures";
import {
ADMIN_USERNAME,
SEED_ACCOUNTS,
SEED_HOUSEHOLDS,
SEED_USERS,
type SeedUser,
} from "./fixtures";
/**
* İdempotent seed. Kullanıcılar Better Auth API'siyle oluşturulur (şifreler doğru hashlenir);
@@ -26,12 +34,24 @@ export type SeedAccountRow = {
};
export type SeedSummary = {
created: { users: number; households: number; memberships: number };
created: {
users: number;
households: number;
memberships: number;
categories: number;
accounts: number;
};
accounts: SeedAccountRow[];
};
const AUTH_COLLECTIONS = ["user", "account", "session", "verification", "rateLimit"];
const DOMAIN_COLLECTIONS = ["households", "householdMembers", "auditLogs"];
const DOMAIN_COLLECTIONS = [
"households",
"householdMembers",
"auditLogs",
"categories",
"accounts",
];
type AuthApi = ReturnType<typeof getAuth>["api"];
@@ -73,7 +93,7 @@ export async function runSeed({
const db = getDb();
await connectMongoose();
const summary: SeedSummary = {
created: { users: 0, households: 0, memberships: 0 },
created: { users: 0, households: 0, memberships: 0, categories: 0, accounts: 0 },
accounts: [],
};
@@ -180,7 +200,53 @@ export async function runSeed({
}
}
// 5) Geliştirme hesapları tablosu
// 5) Varsayılan kategoriler ve örnek hesaplar
const householdIds = new Map<string, Types.ObjectId>();
for (const h of SEED_HOUSEHOLDS) {
const doc = await HouseholdModel.findOne({ name: h.name }).select({ _id: 1 }).lean();
householdIds.set(h.name, doc!._id);
summary.created.categories += await installDefaultCategories(doc!._id, actor);
}
const openingDate = new Date(Date.now() - 183 * 24 * 60 * 60 * 1000);
for (const [order, a] of SEED_ACCOUNTS.entries()) {
const householdId = householdIds.get(a.household)!;
if (await AccountModel.exists({ householdId, name: a.name })) continue;
const payer = a.creditCard
? await AccountModel.findOne({ householdId, name: a.creditCard.paymentAccount })
.select({ _id: 1 })
.lean()
: null;
await AccountModel.create({
householdId,
name: a.name,
type: a.type,
institution: a.institution ?? "",
mealCardProvider: a.mealCardProvider ?? null,
openingBalanceMinor: a.openingBalanceMinor,
openingDate,
color: a.color,
icon: a.icon,
order,
ownerUserId: a.owner ? new Types.ObjectId(ids.get(a.owner)!) : null,
isPrivate: a.isPrivate ?? false,
overdraft: a.overdraft ? { enabled: true, ...a.overdraft } : null,
creditCard: a.creditCard
? {
limitMinor: a.creditCard.limitMinor,
statementDay: a.creditCard.statementDay,
dueRule: { kind: "daysAfter", value: a.creditCard.dueDays },
paymentAccountId: payer?._id ?? null,
}
: null,
createdBy: actor,
updatedBy: actor,
});
summary.created.accounts++;
}
if (summary.created.categories) log(`✓ Varsayılan kategoriler: ${summary.created.categories}`);
if (summary.created.accounts) log(`✓ Örnek hesaplar: ${summary.created.accounts}`);
// 6) Geliştirme hesapları tablosu
const all = [
{ username: ADMIN_USERNAME, name: "Yönetici", email: adminEmail, role: "admin" as const },
...SEED_USERS,