5648eafd7c
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
159 lines
4.5 KiB
TypeScript
159 lines
4.5 KiB
TypeScript
import type { Types } from "mongoose";
|
||
import { createContact, createContactEntry } from "@/features/contacts/service";
|
||
import { AccountModel } from "@/models/account";
|
||
import { ContactModel } from "@/models/contact";
|
||
import type { ContactEntryKind, ContactRelation } from "@/shared/contacts";
|
||
import { todayIstanbul } from "@/shared/dates";
|
||
import { formatMoneyInput } from "@/shared/money";
|
||
import { addDays } from "@/shared/recurrence";
|
||
import { contactEntrySchema, contactFormSchema } from "@/shared/schemas/contact";
|
||
|
||
/**
|
||
* Örnek cariler (Faz 8a): vadesi yaklaşan alacak, kısmen ödenen borç, vadesi geçmiş küçük alacak
|
||
* ve "yalnızca ben" cari. İdempotent: cari `seedRef` ile; hareketler yalnızca cari ilk
|
||
* oluşturulduğunda eklenir.
|
||
*/
|
||
type SeedContact = {
|
||
ref: string;
|
||
household: string;
|
||
by: string;
|
||
name: string;
|
||
relation: ContactRelation;
|
||
phone?: string;
|
||
isPrivate?: boolean;
|
||
dueInDays?: number;
|
||
reminderDays?: number;
|
||
entries: {
|
||
kind: ContactEntryKind;
|
||
account: string;
|
||
amountMinor: number;
|
||
daysAgo: number;
|
||
description?: string;
|
||
}[];
|
||
};
|
||
|
||
const CONTACTS: SeedContact[] = [
|
||
{
|
||
ref: "ahmet",
|
||
household: "Çakır Ailesi",
|
||
by: "admin",
|
||
name: "Ahmet Yılmaz",
|
||
relation: "friend",
|
||
phone: "0532 000 00 01",
|
||
dueInDays: 5,
|
||
reminderDays: 7,
|
||
entries: [
|
||
{
|
||
kind: "lend",
|
||
account: "Ziraat Maaş",
|
||
amountMinor: 5_000_00,
|
||
daysAgo: 70,
|
||
description: "Araba tamiri için",
|
||
},
|
||
{ kind: "collect", account: "Cüzdan", amountMinor: 2_000_00, daysAgo: 30 },
|
||
],
|
||
},
|
||
{
|
||
ref: "hasan",
|
||
household: "Çakır Ailesi",
|
||
by: "admin",
|
||
name: "Hasan Çakır",
|
||
relation: "family",
|
||
dueInDays: 60,
|
||
entries: [
|
||
{
|
||
kind: "borrow",
|
||
account: "Ziraat Maaş",
|
||
amountMinor: 20_000_00,
|
||
daysAgo: 120,
|
||
description: "Ev eşyası için",
|
||
},
|
||
{ kind: "repay", account: "Ziraat Maaş", amountMinor: 5_000_00, daysAgo: 60 },
|
||
{ kind: "repay", account: "Ziraat Maaş", amountMinor: 5_000_00, daysAgo: 10 },
|
||
],
|
||
},
|
||
{
|
||
ref: "elif",
|
||
household: "Çakır Ailesi",
|
||
by: "ayse",
|
||
name: "Elif (komşu)",
|
||
relation: "neighbor",
|
||
dueInDays: -2,
|
||
entries: [
|
||
{
|
||
kind: "lend",
|
||
account: "Cüzdan",
|
||
amountMinor: 300_00,
|
||
daysAgo: 12,
|
||
description: "Pazar alışverişi",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
ref: "selin",
|
||
household: "Çakır Ailesi",
|
||
by: "ayse",
|
||
name: "Selin (iş arkadaşı)",
|
||
relation: "work",
|
||
isPrivate: true,
|
||
entries: [{ kind: "lend", account: "Cüzdan", amountMinor: 1_000_00, daysAgo: 8 }],
|
||
},
|
||
{
|
||
ref: "ali",
|
||
household: "Annemler",
|
||
by: "fatma",
|
||
name: "Ali Demir",
|
||
relation: "family",
|
||
dueInDays: 45,
|
||
entries: [{ kind: "borrow", account: "Vakıfbank Emekli", amountMinor: 3_000_00, daysAgo: 25 }],
|
||
},
|
||
];
|
||
|
||
export async function seedContacts(
|
||
householdIds: Map<string, Types.ObjectId>,
|
||
userIds: Map<string, string>,
|
||
): Promise<number> {
|
||
const today = todayIstanbul();
|
||
let created = 0;
|
||
for (const c of CONTACTS) {
|
||
const householdId = householdIds.get(c.household)!;
|
||
const seedRef = `contact:${c.ref}`;
|
||
if (await ContactModel.exists({ householdId, seedRef })) continue;
|
||
const by = userIds.get(c.by)!;
|
||
const oldest = Math.max(...c.entries.map((e) => e.daysAgo));
|
||
const r = await createContact(
|
||
by,
|
||
String(householdId),
|
||
contactFormSchema.parse({
|
||
name: c.name,
|
||
relation: c.relation,
|
||
phone: c.phone ?? "",
|
||
openingDate: addDays(today, -oldest - 1),
|
||
isPrivate: c.isPrivate ?? false,
|
||
dueDate: c.dueInDays !== undefined ? addDays(today, c.dueInDays) : null,
|
||
reminderDays: c.reminderDays ?? 3,
|
||
}),
|
||
);
|
||
if (!r.ok) throw new Error(`Seed carisi oluşturulamadı (${c.name}): ${r.error}`);
|
||
await ContactModel.updateOne({ _id: r.data.id }, { $set: { seedRef } });
|
||
for (const e of c.entries) {
|
||
const account = await AccountModel.findOne({ householdId, name: e.account }).lean();
|
||
const x = await createContactEntry(
|
||
by,
|
||
String(householdId),
|
||
r.data.id,
|
||
contactEntrySchema.parse({
|
||
kind: e.kind,
|
||
accountId: String(account!._id),
|
||
amount: formatMoneyInput(e.amountMinor),
|
||
date: addDays(today, -e.daysAgo),
|
||
description: e.description ?? "",
|
||
}),
|
||
);
|
||
if (!x.ok) throw new Error(`Seed cari hareketi oluşturulamadı (${c.name}): ${x.error}`);
|
||
}
|
||
created++;
|
||
}
|
||
return created;
|
||
}
|