diff --git a/api/app/Models/Organisation.php b/api/app/Models/Organisation.php index 5be35671..79f0dd6b 100644 --- a/api/app/Models/Organisation.php +++ b/api/app/Models/Organisation.php @@ -11,11 +11,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\SoftDeletes; +use Spatie\Activitylog\Models\Concerns\LogsActivity; +use Spatie\Activitylog\Support\LogOptions; final class Organisation extends Model { use HasFactory; use HasUlids; + use LogsActivity; use SoftDeletes; protected $fillable = [ @@ -41,6 +44,15 @@ final class Organisation extends Model ]; } + public function getActivitylogOptions(): LogOptions + { + return LogOptions::defaults() + ->logOnly(['name', 'slug', 'contact_name', 'contact_email', 'phone', 'website']) + ->logOnlyDirty() + ->dontLogEmptyChanges() + ->useLogName('organisation'); + } + public function users(): BelongsToMany { return $this->belongsToMany(User::class, 'organisation_user') diff --git a/api/tests/Feature/Organisation/OrganisationTest.php b/api/tests/Feature/Organisation/OrganisationTest.php index 5ba30238..87751341 100644 --- a/api/tests/Feature/Organisation/OrganisationTest.php +++ b/api/tests/Feature/Organisation/OrganisationTest.php @@ -9,6 +9,7 @@ use App\Models\User; use Database\Seeders\RoleSeeder; use Illuminate\Foundation\Testing\RefreshDatabase; use Laravel\Sanctum\Sanctum; +use Spatie\Activitylog\Models\Activity; use Tests\TestCase; class OrganisationTest extends TestCase @@ -282,4 +283,48 @@ class OrganisationTest extends TestCase $response->assertUnprocessable() ->assertJsonValidationErrors(['website']); } + + public function test_update_logs_activity_for_changed_fields(): void + { + $user = User::factory()->create(); + $org = Organisation::factory()->create(['name' => 'Old Name']); + $org->users()->attach($user, ['role' => 'org_admin']); + + Sanctum::actingAs($user); + + Activity::query()->delete(); + + $this->putJson("/api/v1/organisations/{$org->id}", [ + 'name' => 'New Name', + 'contact_email' => 'new@example.com', + ])->assertOk(); + + $activities = Activity::where('log_name', 'organisation') + ->where('subject_type', Organisation::class) + ->where('subject_id', $org->id) + ->get(); + + $this->assertCount(1, $activities); + $changes = $activities->first()->attribute_changes; + $this->assertSame('New Name', $changes['attributes']['name']); + $this->assertSame('Old Name', $changes['old']['name']); + $this->assertSame('new@example.com', $changes['attributes']['contact_email']); + } + + public function test_update_does_not_log_activity_when_no_tracked_fields_change(): void + { + $user = User::factory()->create(); + $org = Organisation::factory()->create(['name' => 'Stable Name']); + $org->users()->attach($user, ['role' => 'org_admin']); + + Sanctum::actingAs($user); + + Activity::query()->delete(); + + $this->putJson("/api/v1/organisations/{$org->id}", [ + 'name' => 'Stable Name', + ])->assertOk(); + + $this->assertSame(0, Activity::where('log_name', 'organisation')->count()); + } }