121 lines
3.8 KiB
PHP
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',
|
|
};
|
|
}
|
|
}
|