import { model, models, Schema, type InferSchemaType, type Model } from "mongoose"; import { FREQUENCIES, MONTHLY_MODES } from "@/shared/recurrence"; import { TRANSACTION_TYPES } from "@/shared/transactions"; /** * Düzenli işlem kuralı (Bölüm 6.7). Her tekrar için `planned` durumunda bir işlem üretilir * (`transactions.recurringRuleId` + `occurrenceIndex`, benzersiz). Bitiş tarihsiz kurallarda * ufuk 12 ay; okuma sırasında ilerletilir. */ const recurringRuleSchema = new Schema( { householdId: { type: Schema.Types.ObjectId, required: true }, // İşlem şablonu (bölme yok). type: { type: String, enum: TRANSACTION_TYPES, required: true }, amountMinor: { type: Number, required: true, min: 1 }, /** Tutar tahmini mi (ör. fatura)? Onaylarken düzeltilir. */ isEstimate: { type: Boolean, default: false }, accountId: { type: Schema.Types.ObjectId, required: true }, toAccountId: { type: Schema.Types.ObjectId, default: null }, categoryId: { type: Schema.Types.ObjectId, default: null }, payeeName: { type: String, default: "", maxlength: 80 }, description: { type: String, default: "", maxlength: 500 }, tags: { type: [String], default: [] }, // Tekrar. frequency: { type: String, enum: FREQUENCIES, required: true }, interval: { type: Number, default: 1, min: 1, max: 12 }, monthlyMode: { type: String, enum: MONTHLY_MODES, default: "day" }, /** "YYYY-MM-DD" (İstanbul günü). */ startDate: { type: String, required: true }, endDate: { type: String, default: null }, count: { type: Number, default: null, min: 1 }, /** Üretilen son ufuk ("YYYY-MM-DD"); null → hiç üretilmedi. */ generatedUntil: { type: String, default: null }, deletedAt: { type: Date, default: null }, seedRef: { type: String, default: null }, createdBy: { type: Schema.Types.ObjectId, required: true }, updatedBy: { type: Schema.Types.ObjectId, required: true }, }, { timestamps: true, collection: "recurringRules" }, ); recurringRuleSchema.index({ householdId: 1, deletedAt: 1, generatedUntil: 1 }); recurringRuleSchema.index( { householdId: 1, seedRef: 1 }, { unique: true, partialFilterExpression: { seedRef: { $type: "string" } } }, ); export type RecurringRule = InferSchemaType; export const RecurringRuleModel: Model = (models.RecurringRule as Model | undefined) ?? model("RecurringRule", recurringRuleSchema);