'array', 'created_at' => 'datetime', ]; // ========================================================================= // RELATIONSHIPS // ========================================================================= public function chunk(): BelongsTo { return $this->belongsTo(DocumentChunk::class, 'document_chunk_id'); } public function user(): BelongsTo { return $this->belongsTo(User::class); } // ========================================================================= // FACTORY METHOD // ========================================================================= /** * Cipta satu rekod audit dengan data dari request semasa. * * @param int $chunkId ID chunk yang terlibat * @param string $operation Jenis operasi (guna konstant OP_*) * @param array $data Data tambahan (old_final_text, new_status, metadata, dll.) * @param string|null $notes Nota admin */ public static function record( int $chunkId, string $operation, array $data = [], ?string $notes = null ): static { return static::create(array_merge([ 'document_chunk_id' => $chunkId, 'user_id' => auth()->id(), 'operation' => $operation, 'notes' => $notes, 'ip_address' => request()->ip(), 'created_at' => now(), ], $data)); } // ========================================================================= // DISPLAY HELPERS // ========================================================================= public function getOperationLabel(): string { return match ($this->operation) { self::OP_EDIT_FINAL_TEXT => 'Edit Final Text', self::OP_EXCLUDE => 'Dikecualikan', self::OP_INCLUDE => 'Dikembalikan', self::OP_REINDEX => 'Reindex', self::OP_SPLIT_PARENT => 'Split (asal)', self::OP_SPLIT_CHILD => 'Split (baharu)', default => ucfirst(str_replace('_', ' ', $this->operation)), }; } public function getOperationBadgeClass(): string { return match ($this->operation) { self::OP_EDIT_FINAL_TEXT => 'bg-primary', self::OP_EXCLUDE => 'bg-secondary', self::OP_INCLUDE => 'bg-success', self::OP_REINDEX => 'bg-info text-dark', self::OP_SPLIT_PARENT => 'bg-warning text-dark', self::OP_SPLIT_CHILD => 'bg-warning text-dark', default => 'bg-light text-dark border', }; } }