This commit is contained in:
Marcus Moore 2025-03-06 01:06:37 +00:00 committed by GitHub
commit 94b0574a23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 56 additions and 11 deletions

View file

@ -184,15 +184,15 @@ class AccessoriesController extends Controller
*/
public function destroy($accessoryId) : RedirectResponse
{
if (is_null($accessory = Accessory::find($accessoryId))) {
if (is_null($accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
}
$this->authorize($accessory);
if ($accessory->hasUsers() > 0) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', ['count'=> $accessory->hasUsers()]));
if ($accessory->checkouts_count > 0) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/general.delete_disabled'));
}
if ($accessory->image) {

View file

@ -249,11 +249,11 @@ class AccessoriesController extends Controller
public function destroy($id)
{
$this->authorize('delete', Accessory::class);
$accessory = Accessory::findOrFail($id);
$accessory = Accessory::withCount('checkouts as checkouts_count')->findOrFail($id);
$this->authorize($accessory);
if ($accessory->hasUsers() > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.assoc_users', ['count'=> $accessory->hasUsers()])));
if ($accessory->checkouts_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/general.delete_disabled')));
}
$accessory->delete();

View file

@ -53,7 +53,7 @@ class AccessoriesTransformer
'checkout' => Gate::allows('checkout', Accessory::class),
'checkin' => false,
'update' => Gate::allows('update', Accessory::class),
'delete' => Gate::allows('delete', Accessory::class),
'delete' => $accessory->checkouts_count === 0 && Gate::allows('delete', Accessory::class),
'clone' => Gate::allows('create', Accessory::class),
];

View file

@ -3,6 +3,7 @@
namespace Database\Factories;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\Category;
use App\Models\Location;
use App\Models\Manufacturer;
@ -170,4 +171,30 @@ class AccessoryFactory extends Factory
}
});
}
public function checkedOutToAsset(Asset $asset = null)
{
return $this->afterCreating(function (Accessory $accessory) use ($asset) {
$accessory->checkouts()->create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => 1,
'assigned_to' => $asset->id ?? Asset::factory()->create()->id,
'assigned_type' => Asset::class,
]);
});
}
public function checkedOutToLocation(Location $location = null)
{
return $this->afterCreating(function (Accessory $accessory) use ($location) {
$accessory->checkouts()->create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => 1,
'assigned_to' => $location->id ?? Location::factory()->create()->id,
'assigned_type' => Location::class,
]);
});
}
}

View file

@ -5,6 +5,7 @@ namespace Tests\Feature\Accessories\Api;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\Concerns\TestsFullMultipleCompaniesSupport;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
@ -53,9 +54,17 @@ class DeleteAccessoriesTest extends TestCase implements TestsFullMultipleCompani
$this->assertSoftDeleted($accessoryC);
}
public function testCannotDeleteAccessoryThatHasCheckouts()
public static function checkedOutAccessories()
{
$accessory = Accessory::factory()->checkedOutToUser()->create();
yield 'checked out to user' => [fn() => Accessory::factory()->checkedOutToUser()->create()];
yield 'checked out to asset' => [fn() => Accessory::factory()->checkedOutToAsset()->create()];
yield 'checked out to location' => [fn() => Accessory::factory()->checkedOutToLocation()->create()];
}
#[DataProvider('checkedOutAccessories')]
public function testCannotDeleteAccessoryThatHasCheckouts($data)
{
$accessory = $data();
$this->actingAsForApi(User::factory()->deleteAccessories()->create())
->deleteJson(route('api.accessories.destroy', $accessory))

View file

@ -5,6 +5,7 @@ namespace Tests\Feature\Accessories\Ui;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use PHPUnit\Framework\Attributes\DataProvider;
use Tests\TestCase;
class DeleteAccessoryTest extends TestCase
@ -29,9 +30,17 @@ class DeleteAccessoryTest extends TestCase
$this->assertFalse($accessoryForCompanyA->refresh()->trashed(), 'Accessory should not be deleted');
}
public function testCannotDeleteAccessoryThatHasCheckouts()
public static function checkedOutAccessories()
{
$accessory = Accessory::factory()->checkedOutToUser()->create();
yield 'checked out to user' => [fn() => Accessory::factory()->checkedOutToUser()->create()];
yield 'checked out to asset' => [fn() => Accessory::factory()->checkedOutToAsset()->create()];
yield 'checked out to location' => [fn() => Accessory::factory()->checkedOutToLocation()->create()];
}
#[DataProvider('checkedOutAccessories')]
public function testCannotDeleteAccessoryThatHasCheckouts($data)
{
$accessory = $data();
$this->actingAs(User::factory()->deleteAccessories()->create())
->delete(route('accessories.destroy', $accessory->id))