Files
ChatbotAI/app/Models/ChunkAudit.php
2026-05-18 08:56:23 +08:00

121 lines
3.8 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* ChunkAudit
*
* Audit trail khusus untuk operasi chunk.
* Append-only — tiada update atau delete.
*
* Berbeza dari AuditLog: ChunkAudit menyimpan perubahan teks penuh (old/new final_text)
* yang terlalu besar untuk JSON kolum dalam audit_logs.
*/
class ChunkAudit extends Model
{
// Append-only — tiada updated_at
const UPDATED_AT = null;
// === Operation constants ===
const OP_EDIT_FINAL_TEXT = 'edit_final_text';
const OP_EXCLUDE = 'exclude';
const OP_INCLUDE = 'include';
const OP_REINDEX = 'reindex';
const OP_SPLIT_PARENT = 'split_parent';
const OP_SPLIT_CHILD = 'split_child';
protected $fillable = [
'document_chunk_id',
'user_id',
'operation',
'old_final_text',
'new_final_text',
'old_status',
'new_status',
'metadata',
'notes',
'ip_address',
'created_at',
];
protected $casts = [
'metadata' => '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',
};
}
}