feat(models): households ve householdMembers Mongoose modelleri

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 02:14:10 +03:00
parent 3e11a34235
commit 38e2a7a26d
3 changed files with 78 additions and 0 deletions
View File
+26
View File
@@ -0,0 +1,26 @@
import { model, models, Schema, type InferSchemaType, type Model } from "mongoose";
import { HOUSEHOLD_ROLES } from "@/features/households/types";
/** Kullanıcının bir hanedeki üyeliği ve hane içi rolü (owner | member | viewer). */
const householdMemberSchema = new Schema(
{
householdId: { type: Schema.Types.ObjectId, ref: "Household", required: true },
/** Better Auth `user` koleksiyonundaki _id. */
userId: { type: Schema.Types.ObjectId, required: true },
role: { type: String, enum: HOUSEHOLD_ROLES, required: true },
createdBy: { type: Schema.Types.ObjectId, required: true },
updatedBy: { type: Schema.Types.ObjectId, required: true },
},
{ timestamps: true, collection: "householdMembers" },
);
// Bir kullanıcı bir hanede yalnızca bir kez üye olabilir.
householdMemberSchema.index({ householdId: 1, userId: 1 }, { unique: true });
// Kullanıcının hanelerini hızlı listelemek için.
householdMemberSchema.index({ userId: 1, householdId: 1 });
export type HouseholdMember = InferSchemaType<typeof householdMemberSchema>;
export const HouseholdMemberModel: Model<HouseholdMember> =
(models.HouseholdMember as Model<HouseholdMember> | undefined) ??
model<HouseholdMember>("HouseholdMember", householdMemberSchema);
+52
View File
@@ -0,0 +1,52 @@
import {
model,
models,
Schema,
type HydratedDocument,
type InferSchemaType,
type Model,
} from "mongoose";
/** Hane ayarları (Faz 0 kararları: bütçe ayı başlangıcı, taksit ve günlük plan tercihleri). */
const householdSettingsSchema = new Schema(
{
/** Bütçe ayının başlangıç günü (1 = takvim ayı). */
budgetMonthStartDay: { type: Number, min: 1, max: 28, default: 1 },
/** Taksitlerin bütçe etkisi: her taksit kendi ayına | tamamı harcama ayına. */
installmentBudgetMode: {
type: String,
enum: ["per_installment", "purchase_month"],
default: "per_installment",
},
/** Günlük plan: değişken bütçe eşit dağıtılır | önceki ayın örüntüsüne göre. */
dailyPlanMode: { type: String, enum: ["even", "previous_month_pattern"], default: "even" },
/** "Yalnızca ben" hesapları hane toplamlarına dahil edilsin mi? */
includePrivateAccountsInTotals: { type: Boolean, default: true },
/** Akıllı mağaza önerisi: ek mağaza ancak tasarruf bu tutarı aşarsa (kuruş). */
extraStoreSavingThresholdMinor: { type: Number, min: 0, default: 10_000 },
},
{ _id: false },
);
const householdSchema = new Schema(
{
name: { type: String, required: true, trim: true, minlength: 2, maxlength: 80 },
currency: { type: String, enum: ["TRY"], default: "TRY" },
timezone: { type: String, default: "Europe/Istanbul" },
settings: { type: householdSettingsSchema, default: () => ({}) },
archivedAt: { type: Date, default: null },
createdBy: { type: Schema.Types.ObjectId, required: true },
updatedBy: { type: Schema.Types.ObjectId, required: true },
},
{ timestamps: true, collection: "households" },
);
householdSchema.index({ name: 1 });
export type Household = InferSchemaType<typeof householdSchema>;
export type HouseholdDoc = HydratedDocument<Household>;
/** HMR'de modelin yeniden derlenmesini önler. */
export const HouseholdModel: Model<Household> =
(models.Household as Model<Household> | undefined) ??
model<Household>("Household", householdSchema);