import { model, models, Schema, type InferSchemaType, type Model } from "mongoose"; import { ACCOUNT_TYPES, DUE_RULE_KINDS, MEAL_CARD_PROVIDERS } from "@/shared/accounts"; import { ICON_KEYS, SWATCHES } from "@/shared/appearance"; /** * Hesap (Bölüm 6.1). Tutarlar kuruş. Bakiye işareti: varlık pozitif, kart borcu negatif. * Güncel bakiyenin tek doğruluk kaynağı işlemlerdir (Faz 6b); `balanceCacheMinor` yalnızca önbellek. */ const overdraftSchema = new Schema( { enabled: { type: Boolean, default: false }, limitMinor: { type: Number, min: 0, default: 0 }, /** Aylık faiz oranı, baz puan (4,25% → 425). */ monthlyRateBp: { type: Number, min: 0, max: 10_000, default: null }, statementDay: { type: Number, min: 1, max: 31, default: null }, }, { _id: false }, ); const creditCardSchema = new Schema( { limitMinor: { type: Number, min: 0, default: 0 }, /** Hesap kesim günü; ayda yoksa (31) ayın son günü kullanılır (Faz 7). */ statementDay: { type: Number, min: 1, max: 31, default: 1 }, dueRule: { kind: { type: String, enum: DUE_RULE_KINDS, default: "daysAfter" }, value: { type: Number, min: 1, max: 31, default: 10 }, }, /** * Asgari ödeme oranı, baz puan (2000 = %20). null → varsayılan kural: limit 50.000 TL altı %20, * üstü %40 (Faz 7 kararı). */ minimumPaymentRateBp: { type: Number, min: 0, max: 10_000, default: null }, /** Kart borcunun ödeneceği varsayılan hesap. */ paymentAccountId: { type: Schema.Types.ObjectId, default: null }, }, { _id: false }, ); const accountSchema = new Schema( { householdId: { type: Schema.Types.ObjectId, required: true }, name: { type: String, required: true, trim: true, maxlength: 80 }, type: { type: String, enum: ACCOUNT_TYPES, required: true }, institution: { type: String, trim: true, maxlength: 80, default: "" }, mealCardProvider: { type: String, enum: [...MEAL_CARD_PROVIDERS, null], default: null }, /** İleride döviz hesabı için; şimdilik yalnızca TRY. */ currency: { type: String, enum: ["TRY"], default: "TRY" }, openingBalanceMinor: { type: Number, required: true, default: 0 }, openingDate: { type: Date, required: true }, color: { type: String, enum: SWATCHES, default: "blue" }, icon: { type: String, enum: ICON_KEYS, default: "wallet" }, order: { type: Number, default: 0 }, archivedAt: { type: Date, default: null }, /** Hesabın sahibi kişi (hane üyesi). "Yalnızca ben" hesaplarında bakiyeyi yalnızca o görür. */ ownerUserId: { type: Schema.Types.ObjectId, default: null }, isPrivate: { type: Boolean, default: false }, overdraft: { type: overdraftSchema, default: null }, creditCard: { type: creditCardSchema, default: null }, balanceCacheMinor: { type: Number, default: null }, createdBy: { type: Schema.Types.ObjectId, required: true }, updatedBy: { type: Schema.Types.ObjectId, required: true }, }, { timestamps: true, collection: "accounts" }, ); accountSchema.index({ householdId: 1, archivedAt: 1, order: 1 }); export type Account = InferSchemaType; export const AccountModel: Model = (models.Account as Model | undefined) ?? model("Account", accountSchema);