diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php index 4b9ccb6753..cb4fa5fa5b 100644 --- a/app/Http/Controllers/Assets/BulkAssetsController.php +++ b/app/Http/Controllers/Assets/BulkAssetsController.php @@ -656,6 +656,21 @@ class BulkAssetsController extends Controller ->with('error', trans('general.error_assets_already_checked_out')); } + // Prevent checking out assets across companies if FMCS enabled + if (Setting::getSettings()->full_multiple_companies_support && $target->company_id) { + $company_ids = $assets->pluck('company_id')->unique(); + + // if there is more than one unique company id or the singular company id does not match + // then the checkout is invalid + if ($company_ids->count() > 1 || $company_ids->first() != $target->company_id) { + // re-add the asset ids so the assets select is re-populated + $request->session()->flashInput(['selected_assets' => $asset_ids]); + + return redirect(route('hardware.bulkcheckout.show')) + ->with('error', trans('general.error_user_company_multiple')); + } + } + if (request('checkout_to_type') == 'asset') { foreach ($asset_ids as $asset_id) { if ($target->id == $asset_id) { diff --git a/resources/lang/en-US/general.php b/resources/lang/en-US/general.php index 42751c5cf9..3d7b8ca6bf 100644 --- a/resources/lang/en-US/general.php +++ b/resources/lang/en-US/general.php @@ -519,6 +519,7 @@ return [ 'item_notes' => ':item Notes', 'item_name_var' => ':item Name', 'error_user_company' => 'Checkout target company and asset company do not match', + 'error_user_company_multiple' => 'One or more of the checkout target company and asset company do not match', 'error_user_company_accept_view' => 'An Asset assigned to you belongs to a different company so you can\'t accept nor deny it, please check with your manager', 'error_assets_already_checked_out' => 'One or more of the assets are already checked out', 'importer' => [ diff --git a/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php b/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php index 2f325ba68a..6f6f250b90 100644 --- a/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/BulkAssetCheckoutTest.php @@ -4,6 +4,7 @@ namespace Tests\Feature\Checkouts\Ui; use App\Mail\CheckoutAssetMail; use App\Models\Asset; +use App\Models\Company; use App\Models\Location; use App\Models\User; use Illuminate\Support\Facades\Mail; @@ -122,6 +123,42 @@ class BulkAssetCheckoutTest extends TestCase ]; } + #[DataProvider('checkoutTargets')] + public function test_adheres_to_full_multiple_company_support($data) + { + ['type' => $type, 'target' => $target] = $data(); + + $this->settings->enableMultipleFullCompanySupport(); + + // create two companies + [$companyA, $companyB] = Company::factory()->count(2)->create(); + + // create an asset for each company + $assetForCompanyA = Asset::factory()->for($companyA)->create(); + $assetForCompanyB = Asset::factory()->for($companyB)->create(); + + $this->assertNull($assetForCompanyA->assigned_to, 'Asset should not be assigned before attempting this test case.'); + $this->assertNull($assetForCompanyB->assigned_to, 'Asset should not be assigned before attempting this test case.'); + + // attempt to bulk checkout both items to the target + $response = $this->actingAs(User::factory()->superuser()->create()) + ->post(route('hardware.bulkcheckout.store'), [ + 'selected_assets' => [ + $assetForCompanyA->id, + $assetForCompanyB->id, + ], + 'checkout_to_type' => $type, + "assigned_$type" => $target->id, + ]); + + // ensure bulk checkout is blocked + $this->assertNull($assetForCompanyA->fresh()->assigned_to, 'Asset was checked out across companies.'); + $this->assertNull($assetForCompanyB->fresh()->assigned_to, 'Asset was checked out across companies.'); + + // ensure redirected back + $response->assertRedirectToRoute('hardware.bulkcheckout.show'); + } + #[DataProvider('checkoutTargets')] public function test_prevents_checkouts_of_checked_out_items($data) {