diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php index 9e8ddfd08f..e433475d39 100644 --- a/app/Http/Controllers/Assets/BulkAssetsController.php +++ b/app/Http/Controllers/Assets/BulkAssetsController.php @@ -570,7 +570,6 @@ class BulkAssetsController extends Controller */ public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException { - $this->authorize('checkout', Asset::class); try { @@ -584,6 +583,8 @@ class BulkAssetsController extends Controller $asset_ids = array_filter($request->get('selected_assets')); + $assets = Asset::findOrFail($asset_ids); + if (request('checkout_to_type') == 'asset') { foreach ($asset_ids as $asset_id) { if ($target->id == $asset_id) { @@ -603,9 +604,8 @@ class BulkAssetsController extends Controller } $errors = []; - DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference! - foreach ($asset_ids as $asset_id) { - $asset = Asset::findOrFail($asset_id); + DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $assets, $request) { //NOTE: $errors is passsed by reference! + foreach ($assets as $asset) { $this->authorize('checkout', $asset); $checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null); @@ -632,7 +632,7 @@ class BulkAssetsController extends Controller // Redirect to the asset management page with error return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors); } catch (ModelNotFoundException $e) { - return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors()); + return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $request->input('selected_assets'))); } } diff --git a/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php b/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php new file mode 100644 index 0000000000..08d6cf6841 --- /dev/null +++ b/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php @@ -0,0 +1,91 @@ +actingAs(User::factory()->create()) + ->post(route('hardware.bulkcheckout.store'), [ + 'selected_assets' => [1], + 'checkout_to_type' => 'user', + 'assigned_user' => 1, + 'assigned_asset' => null, + 'checkout_at' => null, + 'expected_checkin' => null, + 'note' => null, + ]) + ->assertForbidden(); + } + + public function testCanBulkCheckoutAssets() + { + Mail::fake(); + + $assets = Asset::factory()->requiresAcceptance()->count(2)->create(); + $user = User::factory()->create(['email' => 'someone@example.com']); + + $checkoutAt = now()->subWeek()->format('Y-m-d'); + $expectedCheckin = now()->addWeek()->format('Y-m-d'); + + $this->actingAs(User::factory()->checkoutAssets()->viewAssets()->create()) + ->followingRedirects() + ->post(route('hardware.bulkcheckout.store'), [ + 'selected_assets' => $assets->pluck('id')->toArray(), + 'checkout_to_type' => 'user', + 'assigned_user' => $user->id, + 'assigned_asset' => null, + 'checkout_at' => $checkoutAt, + 'expected_checkin' => $expectedCheckin, + 'note' => null, + ]) + ->assertOk(); + + $assets = $assets->fresh(); + + $assets->each(function ($asset) use ($expectedCheckin, $checkoutAt, $user) { + $asset->assignedTo()->is($user); + $asset->last_checkout = $checkoutAt; + $asset->expected_checkin = $expectedCheckin; + }); + + Mail::assertSent(CheckoutAssetMail::class, 2); + Mail::assertSent(CheckoutAssetMail::class, function (CheckoutAssetMail $mail) { + return $mail->hasTo('someone@example.com'); + }); + } + + public function testHandleMissingModelBeingIncluded() + { + Mail::fake(); + + $this->actingAs(User::factory()->checkoutAssets()->create()) + ->post(route('hardware.bulkcheckout.store'), [ + 'selected_assets' => [ + Asset::factory()->requiresAcceptance()->create()->id, + 9999999, + ], + 'checkout_to_type' => 'user', + 'assigned_user' => User::factory()->create(['email' => 'someone@example.com'])->id, + 'assigned_asset' => null, + 'checkout_at' => null, + 'expected_checkin' => null, + 'note' => null, + ]) + ->assertSessionHas('error', trans_choice('admin/hardware/message.multi-checkout.error', 2)); + + try { + Mail::assertNotSent(CheckoutAssetMail::class); + } catch (ExpectationFailedException $e) { + $this->fail('Asset checkout email was sent when the entire checkout failed.'); + } + } +}