Add backend for updating subactivities
This commit is contained in:
parent
13c9d2f2c1
commit
9315dafbfb
|
@ -3,6 +3,7 @@
|
|||
namespace App\Activity\Actions;
|
||||
|
||||
use App\Activity;
|
||||
use App\Member\Membership;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
@ -46,6 +47,12 @@ class ActivityUpdateAction
|
|||
$this->validateNami($activity, $request->validated());
|
||||
}
|
||||
|
||||
$removingSubactivities = $activity->subactivities()->whereNotIn('id', $request->validated('subactivities'))->pluck('id');
|
||||
|
||||
if ($removingSubactivities->first(fn ($subactivity) => Membership::firstWhere(['activity_id' => $activity->id, 'subactivity_id' => $subactivity]))) {
|
||||
throw ValidationException::withMessages(['subactivities' => 'Untergliederung hat noch Mitglieder.']);
|
||||
}
|
||||
|
||||
$this->handle($activity, $request->validated());
|
||||
|
||||
return redirect()->route('activity.index');
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace App\Activity\Api;
|
||||
|
||||
use App\Activity;
|
||||
use App\Member\Membership;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Lorisleiva\Actions\ActionRequest;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class SubactivityUpdateAction
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
/**
|
||||
* @param array<string, string|array<int, int>> $payload
|
||||
*/
|
||||
public function handle(Subactivity $subactivity, array $payload): Subactivity
|
||||
{
|
||||
$subactivity->update(Arr::except($payload, 'activities'));
|
||||
|
||||
if (null !== data_get($payload, 'activities')) {
|
||||
$subactivity->activities()->sync($payload['activities']);
|
||||
}
|
||||
|
||||
return $subactivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:255', Rule::unique('subactivities', 'name')->ignore(request()->route('subactivity')->id)],
|
||||
'activities' => ['present', 'array', 'min:1'],
|
||||
'is_filterable' => 'present|boolean',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function getValidationAttributes(): array
|
||||
{
|
||||
return [
|
||||
'activities' => 'Tätigkeiten',
|
||||
];
|
||||
}
|
||||
|
||||
public function asController(ActionRequest $request, Subactivity $subactivity): JsonResponse
|
||||
{
|
||||
if ($subactivity->hasNami) {
|
||||
$this->validateNami($subactivity, $request->validated());
|
||||
}
|
||||
|
||||
$removingActivities = $subactivity->activities()->whereNotIn('id', $request->validated('activities'))->pluck('id');
|
||||
|
||||
if ($removingActivities->first(fn ($activity) => Membership::firstWhere(['activity_id' => $activity, 'subactivity_id' => $subactivity->id]))) {
|
||||
throw ValidationException::withMessages(['activities' => 'Tätigkeit hat noch Mitglieder.']);
|
||||
}
|
||||
|
||||
return response()->json($this->handle($subactivity, $request->validated()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo handle this with a model event on the pivot model
|
||||
*
|
||||
* @param Payload $payload
|
||||
*/
|
||||
private function validateNami(Subactivity $subactivity, array $payload): void
|
||||
{
|
||||
if ($subactivity->name !== $payload['name']) {
|
||||
throw ValidationException::withMessages(['name' => 'Untertätigkeit ist in NaMi. Update des Namens nicht möglich.']);
|
||||
}
|
||||
|
||||
$removingActivities = $subactivity->activities()->whereNotIn('id', $payload['activities'])->pluck('id');
|
||||
|
||||
if ($removingActivities->first(fn ($activity) => Activity::find($activity)->hasNami)) {
|
||||
throw ValidationException::withMessages(['activities' => 'Tätigkeit kann nicht entfernt werden.']);
|
||||
}
|
||||
|
||||
$addingActivities = collect($payload['activities'])->filter(fn ($activityId) => $subactivity->activities->doesntContain($activityId));
|
||||
|
||||
if ($addingActivities->first(fn ($activity) => Activity::find($activity)->hasNami)) {
|
||||
throw ValidationException::withMessages(['activities' => 'Tätigkeit kann nicht hinzugefügt werden.']);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use App\Activity\Actions\DestroyAction as ActivityDestroyAction;
|
|||
use App\Activity\Actions\EditAction as ActivityEditAction;
|
||||
use App\Activity\Actions\IndexAction as ActivityIndexAction;
|
||||
use App\Activity\Api\SubactivityStoreAction;
|
||||
use App\Activity\Api\SubactivityUpdateAction;
|
||||
use App\Contribution\Actions\FormAction as ContributionFormAction;
|
||||
use App\Contribution\ContributionController;
|
||||
use App\Course\Controllers\CourseController;
|
||||
|
@ -62,4 +63,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
Route::patch('/activity/{activity}', ActivityUpdateAction::class)->name('activity.update');
|
||||
Route::delete('/activity/{activity}', ActivityDestroyAction::class)->name('activity.destroy');
|
||||
Route::post('/subactivity', SubactivityStoreAction::class)->name('api.subactivity.store');
|
||||
Route::patch('/subactivity/{subactivity}', SubactivityUpdateAction::class)->name('api.subactivity.update');
|
||||
});
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Tests\Feature\Activity;
|
||||
|
||||
use App\Activity;
|
||||
use App\Member\Member;
|
||||
use App\Member\Membership;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\TestCase;
|
||||
|
@ -86,4 +88,191 @@ class SubactivityTest extends TestCase
|
|||
]);
|
||||
$this->assertDatabaseMissing('subactivities', ['nami_id' => 556]);
|
||||
}
|
||||
|
||||
public function testItCannotUpdateNameIfInNami(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->inNami(777)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'aaaa',
|
||||
'nami_id' => 777,
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['name' => 'Untertätigkeit ist in NaMi. Update des Namens nicht möglich.']);
|
||||
}
|
||||
|
||||
public function testItCannotUpdateNamiId(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->inNami(777)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'nami_id' => 556,
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('subactivities', [
|
||||
'id' => $subactivity->id,
|
||||
'nami_id' => 777,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testItCannotSetNamiId(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'nami_id' => 556,
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('subactivities', [
|
||||
'id' => $subactivity->id,
|
||||
'nami_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testItCanUpdateIsFilterableIfInNami(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->filterable()->inNami(777)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('subactivities', [
|
||||
'id' => $subactivity->id,
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function testItCanUpdateNameWhenNotInNami(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'def',
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('subactivities', [
|
||||
'id' => $subactivity->id,
|
||||
'name' => 'def',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testNameShouldBeUnique(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->inNami(123)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->create();
|
||||
Subactivity::factory()->hasAttached($activity)->name('def')->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'def',
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['name' => 'Name ist bereits vergeben']);
|
||||
}
|
||||
|
||||
public function testItCanSetAnotherActivity(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$newActivity = Activity::factory()->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [$activity->id, $newActivity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('activity_subactivity', ['activity_id' => $activity->id, 'subactivity_id' => $subactivity->id]);
|
||||
$this->assertDatabaseHas('activity_subactivity', ['activity_id' => $newActivity->id, 'subactivity_id' => $subactivity->id]);
|
||||
}
|
||||
|
||||
public function testItCannotSetAnotherNamiActivity(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$newActivity = Activity::factory()->inNami(556)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->name('abc')->inNami(667)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [$activity->id, $newActivity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['activities' => 'Tätigkeit kann nicht hinzugefügt werden.']);
|
||||
}
|
||||
|
||||
public function testItCannotRemoveANamiActivity(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$newActivity = Activity::factory()->inNami(556)->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->hasAttached($newActivity)->name('abc')->inNami(667)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [$activity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['activities' => 'Tätigkeit kann nicht entfernt werden.']);
|
||||
}
|
||||
|
||||
public function testItCannotRemoveActivityIfMembershipsHasMembers(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$newActivity = Activity::factory()->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->create();
|
||||
Member::factory()->defaults()->has(Membership::factory()->for($activity)->for($subactivity))->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [$newActivity->id],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['activities' => 'Tätigkeit hat noch Mitglieder.']);
|
||||
}
|
||||
|
||||
public function testItCannotSetNoActivity(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->create();
|
||||
|
||||
$response = $this->patchJson(route('api.subactivity.update', ['subactivity' => $subactivity->id]), [
|
||||
'name' => 'abc',
|
||||
'activities' => [],
|
||||
'is_filterable' => false,
|
||||
]);
|
||||
|
||||
$response->assertJsonValidationErrors(['activities' => 'Tätigkeiten muss mindestens 1 Elemente haben.']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace Tests\Feature\Activity;
|
||||
|
||||
use App\Activity;
|
||||
use App\Member\Member;
|
||||
use App\Member\Membership;
|
||||
use App\Subactivity;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\TestCase;
|
||||
|
@ -158,4 +160,21 @@ class UpdateTest extends TestCase
|
|||
|
||||
$this->assertDatabaseEmpty('activity_subactivity');
|
||||
}
|
||||
|
||||
public function testItCannotSetSubactivityIfItStillHasMembers(): void
|
||||
{
|
||||
$this->login()->loginNami();
|
||||
$activity = Activity::factory()->create();
|
||||
$subactivity = Subactivity::factory()->hasAttached($activity)->create();
|
||||
$newSubactivity = Subactivity::factory()->create();
|
||||
Member::factory()->defaults()->has(Membership::factory()->for($activity)->for($subactivity))->create();
|
||||
|
||||
$response = $this->patch(route('activity.update', ['activity' => $activity]), [
|
||||
'name' => 'abc',
|
||||
'is_filterable' => false,
|
||||
'subactivities' => [$newSubactivity->id],
|
||||
]);
|
||||
|
||||
$response->assertSessionHasErrors(['subactivities' => 'Untergliederung hat noch Mitglieder.']);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue