Fix: Dont run massstore when activities and subactivities dont match

This commit is contained in:
philipp lang 2025-06-13 13:13:11 +02:00
parent 4698c808f8
commit 9853d4e82e
2 changed files with 85 additions and 58 deletions

View File

@ -10,6 +10,7 @@ use App\Maildispatcher\Actions\ResyncAction;
use App\Member\Member; use App\Member\Member;
use App\Member\Membership; use App\Member\Membership;
use App\Subactivity; use App\Subactivity;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Lorisleiva\Actions\ActionRequest; use Lorisleiva\Actions\ActionRequest;
use Lorisleiva\Actions\Concerns\AsAction; use Lorisleiva\Actions\Concerns\AsAction;
@ -26,7 +27,12 @@ class MassStoreAction
{ {
return [ return [
'group_id' => 'required|numeric|exists:groups,id', 'group_id' => 'required|numeric|exists:groups,id',
'activity_id' => 'required|numeric|exists:activities,id', 'activity_id' => ['required', 'numeric', 'exists:activities,id', function($key, $value, $fail) {
$activity = Activity::findOrFail($value);
if ($activity->subactivities->pluck('id')->doesntContain(request()->subactivity_id)) {
return $fail(':attribute ist nicht vorhanden.');
}
}],
'subactivity_id' => 'required|numeric|exists:subactivities,id', 'subactivity_id' => 'required|numeric|exists:subactivities,id',
'members' => 'array', 'members' => 'array',
'members.*' => 'numeric|exists:members,id', 'members.*' => 'numeric|exists:members,id',
@ -64,7 +70,7 @@ class MassStoreAction
}); });
} }
public function asController(ActionRequest $request): void public function asController(ActionRequest $request): JsonResponse
{ {
/** /**
* @var array{members: array<int, int>, group_id: int, activity_id: int, subactivity_id: int} * @var array{members: array<int, int>, group_id: int, activity_id: int, subactivity_id: int}
@ -77,6 +83,16 @@ class MassStoreAction
Subactivity::findOrFail($input['subactivity_id']), Subactivity::findOrFail($input['subactivity_id']),
$input['members'], $input['members'],
); );
return response()->json([], 200);
}
public function getValidationAttributes(): array {
return [
'activity_id' => 'Tätigkeit',
'subactivity_id' => 'Untertätigkeit',
'group_id' => 'Gruppe',
];
} }
/** /**

View File

@ -16,14 +16,41 @@ use Tests\EndToEndTestCase;
use Throwable; use Throwable;
use Zoomyboy\LaravelNami\Fakes\MembershipFake; use Zoomyboy\LaravelNami\Fakes\MembershipFake;
class MassstoreActionTest extends EndToEndTestCase uses(EndToEndTestCase::class);
{
public function testItFiresActionJobWhenUsingController(): void it('testItFiresActionJobWhenUsingController', function() {
{
Queue::fake(); Queue::fake();
$this->login()->loginNami()->withoutExceptionHandling(); $this->login()->loginNami()->withoutExceptionHandling();
$member = Member::factory()->defaults()->create(); $member = Member::factory()->defaults()->create();
$activity = Activity::factory()
->hasAttached(Subactivity::factory())
->create();
$group = Group::factory()->create();
$subactivity = $activity->subactivities()->first();
$this->postJson(route('membership.masslist.store'), [
'members' => [$member->id],
'activity_id' => $activity->id,
'subactivity_id' => $subactivity->id,
'group_id' => $group->id,
]);
MassStoreAction::assertPushed(fn ($action, $params) => $params[0]->is($group) && $params[1]->is($activity) && $params[2]->is($subactivity) && $params[3][0] === $member->id);
});
it('testItCreatesAMembership', function() {
MembershipDestroyAction::partialMock()->shouldReceive('handle')->never();
MembershipStoreAction::partialMock()->shouldReceive('handle')->once();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
MassStoreAction::run($group, $activity, $subactivity, [$member->id]);
});
it('cannot create membership when activity and subactivity doesnt belong together', function() {
$this->login()->loginNami();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create(); $activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create(); $subactivity = Subactivity::factory()->create();
$group = Group::factory()->create(); $group = Group::factory()->create();
@ -33,24 +60,10 @@ class MassstoreActionTest extends EndToEndTestCase
'activity_id' => $activity->id, 'activity_id' => $activity->id,
'subactivity_id' => $subactivity->id, 'subactivity_id' => $subactivity->id,
'group_id' => $group->id, 'group_id' => $group->id,
]); ])->assertJsonValidationErrors(['activity_id' => 'Tätigkeit ist nicht vorhanden.']);
MassStoreAction::assertPushed(fn ($action, $params) => $params[0]->is($group) && $params[1]->is($activity) && $params[2]->is($subactivity) && $params[3][0] === $member->id); });
}
public function testItCreatesAMembership(): void it('testItDeletesAMembership', function() {
{
MembershipDestroyAction::partialMock()->shouldReceive('handle')->never();
MembershipStoreAction::partialMock()->shouldReceive('handle')->once();
$member = Member::factory()->defaults()->create();
$activity = Activity::factory()->create();
$subactivity = Subactivity::factory()->create();
$group = Group::factory()->create();
MassStoreAction::run($group, $activity, $subactivity, [$member->id]);
}
public function testItDeletesAMembership(): void
{
MembershipDestroyAction::partialMock()->shouldReceive('handle')->once(); MembershipDestroyAction::partialMock()->shouldReceive('handle')->once();
MembershipStoreAction::partialMock()->shouldReceive('handle')->never(); MembershipStoreAction::partialMock()->shouldReceive('handle')->never();
ResyncAction::partialMock()->shouldReceive('handle')->once(); ResyncAction::partialMock()->shouldReceive('handle')->once();
@ -58,10 +71,9 @@ class MassstoreActionTest extends EndToEndTestCase
$member = Member::factory()->defaults()->has(Membership::factory()->inLocal('Leiter*in', 'Rover'))->create(); $member = Member::factory()->defaults()->has(Membership::factory()->inLocal('Leiter*in', 'Rover'))->create();
MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []); MassStoreAction::run($member->memberships->first()->group, $member->memberships->first()->activity, $member->memberships->first()->subactivity, []);
} });
public function testItRollsbackWhenDeletionFails(): void it('testItRollsbackWhenDeletionFails', function() {
{
app(MembershipFake::class) app(MembershipFake::class)
->shows(3, ['id' => 55]) ->shows(3, ['id' => 55])
->shows(3, ['id' => 56]) ->shows(3, ['id' => 56])
@ -79,5 +91,4 @@ class MassstoreActionTest extends EndToEndTestCase
} catch (Throwable $e) { } catch (Throwable $e) {
} }
$this->assertDatabaseCount('memberships', 2); $this->assertDatabaseCount('memberships', 2);
} });
}