import { model, models, Schema, type InferSchemaType, type Model } from "mongoose"; import { ATTACHMENT_KINDS } from "@/shared/attachments"; /** Ek dosyanın bağlanabileceği kayıt türleri (ileride: alışveriş fişi, cari hareket…). */ export const ATTACHMENT_OWNER_TYPES = ["transaction", "product"] as const; export type AttachmentOwnerType = (typeof ATTACHMENT_OWNER_TYPES)[number]; /** * Ek dosya meta verisi (Bölüm 7.4). Dosyanın kendisi depolama sürücüsünde, rastgele anahtarla. * - Yüklenince `ownerId: null` (bekleyen); kayıt kaydedilince sahibine bağlanır. * - Bekleyen ek yalnızca yükleyene görünür ve 24 saat içinde bağlanmazsa temizlenir. * - Kayıttan çıkarılan ek `deletedAt` alır; dosya saklama süresi sonunda silinir. */ const attachmentSchema = new Schema( { householdId: { type: Schema.Types.ObjectId, required: true }, ownerType: { type: String, enum: ATTACHMENT_OWNER_TYPES, default: null }, ownerId: { type: Schema.Types.ObjectId, default: null }, kind: { type: String, enum: ATTACHMENT_KINDS, required: true }, /** Saklanan içeriğin türü (görseller her zaman WebP'ye çevrilir). */ mimeType: { type: String, enum: ["image/webp", "application/pdf"], required: true }, /** Kaynak tür (jpeg, png, webp, heic, pdf) — bilgi amaçlı. */ sourceType: { type: String, required: true }, originalName: { type: String, default: "", maxlength: 120 }, size: { type: Number, required: true }, originalSize: { type: Number, required: true }, width: { type: Number, default: null }, height: { type: Number, default: null }, storageKey: { type: String, required: true }, thumbKey: { type: String, default: null }, uploadedBy: { type: Schema.Types.ObjectId, required: true }, /** Kayıt içindeki sıra (carousel sırası). */ order: { type: Number, default: 0 }, deletedAt: { type: Date, default: null }, }, { timestamps: true, collection: "attachments" }, ); attachmentSchema.index({ householdId: 1, ownerType: 1, ownerId: 1, deletedAt: 1, order: 1 }); attachmentSchema.index({ ownerId: 1, createdAt: 1 }); attachmentSchema.index( { deletedAt: 1 }, { partialFilterExpression: { deletedAt: { $type: "date" } } }, ); attachmentSchema.index({ storageKey: 1 }, { unique: true }); export type Attachment = InferSchemaType; export const AttachmentModel: Model = (models.Attachment as Model | undefined) ?? model("Attachment", attachmentSchema);