import { model, models, Schema, type InferSchemaType, type Model } from "mongoose"; import { ICON_KEYS, SWATCHES } from "@/shared/appearance"; import { CATEGORY_KINDS } from "@/shared/schemas/category"; /** Gelir/gider kategori ağacı (Bölüm 6.2). Silme yok; arşivleme (alt ağaçla birlikte). */ const categorySchema = new Schema( { householdId: { type: Schema.Types.ObjectId, required: true }, kind: { type: String, enum: CATEGORY_KINDS, required: true }, name: { type: String, required: true, trim: true, maxlength: 80 }, /** Kardeşler arasında ad tekrarını önlemek için normalize ad (foldTr). */ nameKey: { type: String, required: true }, parentId: { type: Schema.Types.ObjectId, default: null }, /** Kökten üst kategoriye kadar kimlikler (alt ağaç sorguları ve toplama için). */ ancestors: { type: [Schema.Types.ObjectId], default: [] }, icon: { type: String, enum: ICON_KEYS, default: "tag" }, color: { type: String, enum: SWATCHES, default: "slate" }, order: { type: Number, default: 0 }, archivedAt: { type: Date, default: null }, /** Varsayılan setten geldiyse sabit anahtar (tekrar yüklemede kopya olmaz). */ defaultKey: { type: String, default: null }, createdBy: { type: Schema.Types.ObjectId, required: true }, updatedBy: { type: Schema.Types.ObjectId, required: true }, }, { timestamps: true, collection: "categories" }, ); categorySchema.index({ householdId: 1, kind: 1, parentId: 1, order: 1 }); categorySchema.index({ householdId: 1, ancestors: 1 }); categorySchema.index( { householdId: 1, defaultKey: 1 }, { unique: true, partialFilterExpression: { defaultKey: { $type: "string" } } }, ); export type Category = InferSchemaType; export const CategoryModel: Model = (models.Category as Model | undefined) ?? model("Category", categorySchema);