diff --git a/api/fixtures/materialLists.yml b/api/fixtures/materialLists.yml index 57d27c1f10..b42228dab6 100644 --- a/api/fixtures/materialLists.yml +++ b/api/fixtures/materialLists.yml @@ -2,7 +2,7 @@ App\Entity\MaterialList: materialList1: camp: '@camp1' name: Baumarkt - materialList2: + materialList2WithNoItems: camp: '@camp1' name: Packliste materialList3Manager: diff --git a/api/src/Entity/MaterialList.php b/api/src/Entity/MaterialList.php index 0adbc912b1..a69b0cd1eb 100644 --- a/api/src/Entity/MaterialList.php +++ b/api/src/Entity/MaterialList.php @@ -42,6 +42,11 @@ class MaterialList extends BaseEntity implements BelongsToCampInterface, CopyFro /** * The items that are part of this list. */ + #[Assert\Count( + exactly: 0, + exactMessage: 'It\'s not possible to delete a material list as long as it has items linked to it.', + groups: ['delete'] + )] #[ApiProperty(writable: false, example: '["/material_items/1a2b3c4d"]')] #[Groups(['read'])] #[ORM\OneToMany(targetEntity: MaterialItem::class, mappedBy: 'materialList')] diff --git a/api/tests/Api/MaterialItems/UpdateMaterialItemTest.php b/api/tests/Api/MaterialItems/UpdateMaterialItemTest.php index 7f0e3a08d8..b5c7921118 100644 --- a/api/tests/Api/MaterialItems/UpdateMaterialItemTest.php +++ b/api/tests/Api/MaterialItems/UpdateMaterialItemTest.php @@ -14,7 +14,7 @@ class UpdateMaterialItemTest extends ECampApiTestCase { public function testPatchMaterialItemIsDeniedForAnonymousUser() { $materialItem = static::$fixtures['materialItem1']; static::createBasicClient()->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -31,7 +31,7 @@ public function testPatchMaterialItemIsDeniedForUnrelatedUser() { $materialItem = static::$fixtures['materialItem1']; static::createClientWithCredentials(['username' => static::$fixtures['user4unrelated']->getUsername()]) ->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -50,7 +50,7 @@ public function testPatchMaterialItemIsDeniedForInactiveCollaborator() { $materialItem = static::$fixtures['materialItem1']; static::createClientWithCredentials(['username' => static::$fixtures['user5inactive']->getUsername()]) ->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -69,7 +69,7 @@ public function testPatchMaterialItemIsDeniedForGuest() { $materialItem = static::$fixtures['materialItem1']; static::createClientWithCredentials(['username' => static::$fixtures['user3guest']->getUsername()]) ->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -88,7 +88,7 @@ public function testPatchMaterialItemIsAllowedForMember() { $materialItem = static::$fixtures['materialItem1']; static::createClientWithCredentials(['username' => static::$fixtures['user2member']->getUsername()]) ->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -102,7 +102,7 @@ public function testPatchMaterialItemIsAllowedForMember() { 'quantity' => 1500, 'unit' => 'g', '_links' => [ - 'materialList' => ['href' => $this->getIriFor('materialList2')], + 'materialList' => ['href' => $this->getIriFor('materialList2WithNoItems')], 'period' => ['href' => $this->getIriFor('period1')], // 'materialNode' => null, ], @@ -112,7 +112,7 @@ public function testPatchMaterialItemIsAllowedForMember() { public function testPatchMaterialItemIsAllowedForManager() { $materialItem = static::$fixtures['materialItem1']; static::createClientWithCredentials()->request('PATCH', '/material_items/'.$materialItem->getId(), ['json' => [ - 'materialList' => $this->getIriFor('materialList2'), + 'materialList' => $this->getIriFor('materialList2WithNoItems'), 'period' => $this->getIriFor('period1'), 'materialNode' => null, 'article' => 'Mehl', @@ -125,7 +125,7 @@ public function testPatchMaterialItemIsAllowedForManager() { 'quantity' => 1500, 'unit' => 'g', '_links' => [ - 'materialList' => ['href' => $this->getIriFor('materialList2')], + 'materialList' => ['href' => $this->getIriFor('materialList2WithNoItems')], 'period' => ['href' => $this->getIriFor('period1')], // 'materialNode' => null, ], diff --git a/api/tests/Api/MaterialLists/DeleteMaterialListTest.php b/api/tests/Api/MaterialLists/DeleteMaterialListTest.php index 4471761d2b..598d1b562f 100644 --- a/api/tests/Api/MaterialLists/DeleteMaterialListTest.php +++ b/api/tests/Api/MaterialLists/DeleteMaterialListTest.php @@ -10,7 +10,7 @@ */ class DeleteMaterialListTest extends ECampApiTestCase { public function testDeleteMaterialListIsDeniedForAnonymousUser() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createBasicClient()->request('DELETE', '/material_lists/'.$materialList->getId()); $this->assertResponseStatusCodeSame(401); $this->assertJsonContains([ @@ -20,7 +20,7 @@ public function testDeleteMaterialListIsDeniedForAnonymousUser() { } public function testDeleteMaterialListIsDeniedForUnrelatedUser() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createClientWithCredentials(['username' => static::$fixtures['user4unrelated']->getUsername()]) ->request('DELETE', '/material_lists/'.$materialList->getId()) ; @@ -33,7 +33,7 @@ public function testDeleteMaterialListIsDeniedForUnrelatedUser() { } public function testDeleteMaterialListIsDeniedForInactiveCollaborator() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createClientWithCredentials(['username' => static::$fixtures['user5inactive']->getUsername()]) ->request('DELETE', '/material_lists/'.$materialList->getId()) ; @@ -46,7 +46,7 @@ public function testDeleteMaterialListIsDeniedForInactiveCollaborator() { } public function testDeleteMaterialListIsDeniedForGuest() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createClientWithCredentials(['username' => static::$fixtures['user3guest']->getUsername()]) ->request('DELETE', '/material_lists/'.$materialList->getId()) ; @@ -59,7 +59,7 @@ public function testDeleteMaterialListIsDeniedForGuest() { } public function testDeleteMaterialListIsAllowedForMember() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createClientWithCredentials(['username' => static::$fixtures['user2member']->getUsername()]) ->request('DELETE', '/material_lists/'.$materialList->getId()) ; @@ -68,7 +68,7 @@ public function testDeleteMaterialListIsAllowedForMember() { } public function testDeleteMaterialListIsAllowedForManager() { - $materialList = static::$fixtures['materialList1']; + $materialList = static::$fixtures['materialList2WithNoItems']; static::createClientWithCredentials()->request('DELETE', '/material_lists/'.$materialList->getId()); $this->assertResponseStatusCodeSame(204); $this->assertNull($this->getEntityManager()->getRepository(MaterialList::class)->find($materialList->getId())); @@ -84,4 +84,15 @@ public function testDeleteMaterialListFromCampPrototypeIsDeniedForUnrelatedUser( 'detail' => 'Access Denied.', ]); } + + public function testDeleteMaterialListValidatesThatListHasNoItems() { + $materialList = static::$fixtures['materialList1']; + static::createClientWithCredentials()->request('DELETE', '/material_lists/'.$materialList->getId()); + + $this->assertResponseStatusCodeSame(422); + $this->assertJsonContains([ + 'title' => 'An error occurred', + 'detail' => 'materialItems: It\'s not possible to delete a material list as long as it has items linked to it.', + ]); + } } diff --git a/api/tests/Api/MaterialLists/ListMaterialListsTest.php b/api/tests/Api/MaterialLists/ListMaterialListsTest.php index 493f13b57a..bd6fa7b0e2 100644 --- a/api/tests/Api/MaterialLists/ListMaterialListsTest.php +++ b/api/tests/Api/MaterialLists/ListMaterialListsTest.php @@ -34,7 +34,7 @@ public function testListMaterialListsIsAllowedForLoggedInUserButFiltered() { ]); $this->assertEqualsCanonicalizing([ ['href' => $this->getIriFor('materialList1')], - ['href' => $this->getIriFor('materialList2')], + ['href' => $this->getIriFor('materialList2WithNoItems')], ['href' => $this->getIriFor('materialList3Manager')], ['href' => $this->getIriFor('materialList1camp2')], ['href' => $this->getIriFor('materialList1campPrototype')], @@ -56,7 +56,7 @@ public function testListMaterialListsFilteredByCampIsAllowedForCollaborator() { ]); $this->assertEqualsCanonicalizing([ ['href' => $this->getIriFor('materialList1')], - ['href' => $this->getIriFor('materialList2')], + ['href' => $this->getIriFor('materialList2WithNoItems')], ['href' => $this->getIriFor('materialList3Manager')], ], $response->toArray()['_links']['items']); } diff --git a/frontend/src/components/campAdmin/CampCategories.vue b/frontend/src/components/campAdmin/CampCategories.vue index 2df9af936f..2b25275cbb 100644 --- a/frontend/src/components/campAdmin/CampCategories.vue +++ b/frontend/src/components/campAdmin/CampCategories.vue @@ -60,7 +60,7 @@ Displays all periods of a single camp and allows to edit them & create new ones - {{ $tc('components.camp.CampCategories.deleteCategoryQuestion') }} + {{ $tc('components.camp.campCategories.deleteCategoryQuestion') }}
  • {{ category.short }}: {{ category.name }} @@ -70,7 +70,7 @@ Displays all periods of a single camp and allows to edit them & create new ones