'array', 'is_active' => 'boolean', 'is_public' => 'boolean', 'is_embedded' => 'boolean', 'effective_date' => 'date', 'expiry_date' => 'date', 'embedded_at' => 'datetime', ]; // Type constants const TYPE_FAQ = 'faq'; const TYPE_POLICY = 'policy'; const TYPE_NOTE = 'note'; const TYPE_ANNOUNCEMENT = 'announcement'; public static function typeLabels(): array { return [ self::TYPE_FAQ => 'FAQ / Soal Jawab', self::TYPE_POLICY => 'Polisi / Prosedur', self::TYPE_NOTE => 'Nota Dalaman', self::TYPE_ANNOUNCEMENT => 'Pengumuman', ]; } // === Relationships === public function category(): BelongsTo { return $this->belongsTo(Category::class); } public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } // === Scopes === public function scopeActive(Builder $query): Builder { return $query->where('is_active', true); } public function scopePublic(Builder $query): Builder { return $query->where('is_public', true); } public function scopeByType(Builder $query, string $type): Builder { return $query->where('item_type', $type); } public function scopeByCategory(Builder $query, int $categoryId): Builder { return $query->where('category_id', $categoryId); } public function scopeNotEmbedded(Builder $query): Builder { return $query->where('is_embedded', false); } // === Helpers === public function getTypeLabelAttribute(): string { return self::typeLabels()[$this->item_type] ?? $this->item_type; } /** * Bina teks yang akan di-embed — gabung title + content untuk FAQ */ public function getEmbeddableText(): string { if ($this->item_type === self::TYPE_FAQ) { return "Soalan: {$this->title}\nJawapan: {$this->content}"; } return "{$this->title}\n\n{$this->content}"; } public function markAsEmbedded(string $qdrantPointId): void { $this->update([ 'qdrant_point_id' => $qdrantPointId, 'is_embedded' => true, 'embedded_at' => now(), ]); } public function deactivate(): void { $this->update(['is_active' => false]); } }