Add lecturer cleanup job and update profile update functionality

- 🧹 Introduce `lecturers:cleanup` command to delete lecturers without associated courses or events, merging their items into "Einundzwanzig."
- ⚙️ Add `update` method to `UserController` for handling profile updates, allowing name changes while restricting role modifications.
- 🌐 Register `PATCH /api/user` route for profile updates and update related API tests.
- 🧪 Add feature and console tests for `lecturers:cleanup`, covering dry-run, forced deletion, and edge cases.
This commit is contained in:
HolgerHatGarKeineNode
2026-06-16 14:40:40 +02:00
parent c3028b8260
commit 29628b41e9
5 changed files with 199 additions and 3 deletions
@@ -0,0 +1,45 @@
<?php
use App\Models\Course;
use App\Models\Lecturer;
use App\Models\LibraryItem;
it('aborts when the merge target is missing', function () {
Lecturer::factory()->create(['name' => 'Orphan']);
$this->artisan('lecturers:cleanup', ['--force' => true])->assertExitCode(1);
expect(Lecturer::query()->where('name', 'Orphan')->exists())->toBeTrue();
});
it('does nothing on a dry-run', function () {
Lecturer::factory()->create(['name' => 'Einundzwanzig']);
$empty = Lecturer::factory()->create();
$this->artisan('lecturers:cleanup')->assertExitCode(0);
expect(Lecturer::query()->find($empty->id))->not->toBeNull();
});
it('merges library items and deletes empty lecturers with --force', function () {
$target = Lecturer::factory()->create(['name' => 'Einundzwanzig']);
$empty = Lecturer::factory()->create();
$item = LibraryItem::factory()->create(['lecturer_id' => $empty->id]);
$this->artisan('lecturers:cleanup', ['--force' => true])
->expectsConfirmation('This permanently deletes lecturers on this database. Continue?', 'yes')
->assertExitCode(0);
expect(Lecturer::query()->find($empty->id))->toBeNull();
expect($item->fresh()->lecturer_id)->toBe($target->id);
});
it('keeps lecturers that have a course', function () {
Lecturer::factory()->create(['name' => 'Einundzwanzig']);
$withCourse = Lecturer::factory()->create();
Course::factory()->create(['lecturer_id' => $withCourse->id]);
$this->artisan('lecturers:cleanup', ['--force' => true])->assertExitCode(0);
expect(Lecturer::query()->find($withCourse->id))->not->toBeNull();
});