refactor observers, fix policy, add feature tests

This commit is contained in:
2026-05-07 05:31:22 +07:00
parent f5615038b4
commit 8cb9c0eb96
9 changed files with 216 additions and 36 deletions
+17 -6
View File
@@ -12,25 +12,36 @@ use Illuminate\Support\Facades\Auth;
class ActivityObserver
{
public function updated(Activity $activity): void
public function updating(Activity $activity): bool
{
if ($activity->wasChanged('status')) {
if ($activity->isDirty('status')) {
$old = $activity->getOriginal('status');
$new = $activity->status;
// Validasi workflow: draft→pending, pending→approved/rejected
$allowed = [
'draft' => ['pending'],
'pending' => ['approved', 'rejected'],
];
if (isset($allowed[$old]) && ! in_array($new, $allowed[$old])) {
$validTransition = isset($allowed[$old]) && in_array($new, $allowed[$old]);
if (! $validTransition) {
Notification::make()->title('Transisi tidak diizinkan')
->body("Status tidak bisa diubah dari {$old} ke {$new}.")
->danger()->send();
$activity->status = $old;
return;
return false; // batalkan save
}
}
return true;
}
public function updated(Activity $activity): void
{
if ($activity->wasChanged('status')) {
$old = $activity->getOriginal('status');
$new = $activity->status;
ActivityLog::create([
'user_id' => Auth::id(),
+8 -21
View File
@@ -23,12 +23,10 @@ class CashRecordObserver
// Threshold: 500rb2jt → buat approval ketua + notif
if ($record->amount >= 500_000 && $record->amount <= 2_000_000) {
Approval::create([
'model_type' => CashRecord::class,
'model_id' => $record->id,
'required_approvals' => 1,
'status' => 'pending',
]);
Approval::firstOrCreate(
['model_type' => CashRecord::class, 'model_id' => $record->id],
['required_approvals' => 1, 'status' => 'pending']
);
NotificationService::toRole('ketua',
'Transaksi Kas Butuh Persetujuan',
@@ -38,7 +36,7 @@ class CashRecordObserver
);
}
// Threshold: > 2jt → buat voting + notif semua anggota
// Threshold: > 2jt → buat voting (VoteObserver akan notif semua user)
if ($record->amount > 2_000_000) {
Vote::create([
'title' => "Persetujuan Transaksi: {$record->description}",
@@ -50,13 +48,6 @@ class CashRecordObserver
'deadline' => now()->addDays(3),
'created_by' => Auth::id() ?? $record->created_by,
]);
NotificationService::toRole('ketua',
'Voting Transaksi Besar Dibuat',
"Transaksi \"{$record->description}\" senilai Rp " . number_format($record->amount, 0, ',', '.') . " memerlukan voting.",
'warning',
route('filament.admin.resources.votes.index')
);
}
}
@@ -76,13 +67,9 @@ class CashRecordObserver
public function deleting(CashRecord $record): void
{
if ($record->verified_at !== null) {
\Filament\Notifications\Notification::make()
->title('Tidak dapat dihapus')
->body('Transaksi yang sudah diverifikasi tidak dapat dihapus.')
->danger()
->send();
abort(403);
throw new \Illuminate\Auth\Access\AuthorizationException(
'Transaksi yang sudah diverifikasi tidak dapat dihapus.'
);
}
}
}
-5
View File
@@ -12,11 +12,6 @@ class UserObserver
{
public function updated(User $user): void
{
// Pastikan role anggota selalu ada
if (! $user->hasRole('anggota')) {
$user->assignRole('anggota');
}
// Log perubahan status anggota
if ($user->wasChanged('status')) {
MemberStatusLog::create([