Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions coldfront/core/allocation/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,32 @@ def test_allocationcreateview_post_zeroquantity(self):
self.assertContains(response, "Allocation requested.")
self.assertEqual(len(self.project.allocation_set.all()), 2)

def test_allocationcreateview_post_duplicate_project_resource_shows_error(self):
"""Posting an allocation for same project+resource should show error and not create a new allocation"""
self.post_data["resource"] = str(self.resource_tandon.pk)

# Create an existing allocation for (project, resource_tandon)
existing = Allocation.objects.create(
project=self.project,
justification="existing",
quantity=1,
status=AllocationStatusChoice.objects.get(name="New"),
)
existing.resources.add(self.resource_tandon)

initial_count = self.project.allocation_set.count()

response = self.client.post(self.url, data=self.post_data, follow=True)

self.assertEqual(response.status_code, 200)
# Should not create a new allocation
self.assertEqual(self.project.allocation_set.count(), initial_count)

# Should show the friendly error message you added in form_valid
self.assertContains(
response,
"An allocation for this project and resource already exists.",
)

class AllocationAddUsersViewTest(AllocationViewBaseTest):
"""Tests for the AllocationAddUsersView"""
Expand Down
9 changes: 9 additions & 0 deletions coldfront/core/allocation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import plotly.express as px
from plotly.offline import plot
from django.http import HttpResponse, HttpResponseBadRequest
from django.db import IntegrityError, transaction

ALLOCATION_ENABLE_ALLOCATION_RENEWAL = import_from_settings(
"ALLOCATION_ENABLE_ALLOCATION_RENEWAL", True
Expand Down Expand Up @@ -690,6 +691,14 @@ def form_valid(self, form):
)
return self.form_invalid(form)

# Prevent duplicate allocation for same (project, resource)
if Allocation.objects.filter(project=project_obj, resources=resource_obj).exists():
form.add_error(
"resource",
"An allocation for this project and resource already exists.",
)
return self.form_invalid(form)

usernames = form_data.get("users")
usernames.append(project_obj.pi.username)
usernames = list(set(usernames))
Expand Down
68 changes: 2 additions & 66 deletions coldfront/core/utils/management/commands/load_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,43 +269,7 @@ def handle(self, *args, **options):
start_date = datetime.datetime.now()
end_date = datetime.datetime.now() + relativedelta(days=365)

# Add PI cluster
allocation_obj, _ = Allocation.objects.get_or_create(
project=project_obj,
status=AllocationStatusChoice.objects.get(name="Active"),
start_date=start_date,
end_date=end_date,
is_changeable=True,
justification="I need access to my nodes.",
)

allocation_obj.resources.add(Resource.objects.get(name="Tandon"))
allocation_obj.save()

allocation_attribute_type_obj = AllocationAttributeType.objects.get(
name="slurm_account_name"
)
AllocationAttribute.objects.get_or_create(
allocation_attribute_type=allocation_attribute_type_obj,
allocation=allocation_obj,
value=f"torch_pr_{allocation_obj.project.pk}_Tandon",
)

allocation_attribute_type_obj = AllocationAttributeType.objects.get(
name="slurm_user_specs"
)
AllocationAttribute.objects.get_or_create(
allocation_attribute_type=allocation_attribute_type_obj,
allocation=allocation_obj,
value="Fairshare=parent",
)

allocation_user_obj = AllocationUser.objects.create(
allocation=allocation_obj,
user=pi1,
status=AllocationUserStatusChoice.objects.get(name="Active"),
)
# Add university cluster
# Add university allocation
allocation_obj, _ = Allocation.objects.get_or_create(
project=project_obj,
status=AllocationStatusChoice.objects.get(name="Active"),
Expand Down Expand Up @@ -363,41 +327,13 @@ def handle(self, *args, **options):
value="2022-01-01",
)

allocation_user_obj = AllocationUser.objects.create(
allocation=allocation_obj,
user=pi1,
status=AllocationUserStatusChoice.objects.get(name="Active"),
)
# Add project storage
allocation_obj, _ = Allocation.objects.get_or_create(
project=project_obj,
status=AllocationStatusChoice.objects.get(name="Active"),
start_date=start_date,
end_date=end_date,
quantity=10,
is_changeable=True,
justification="I need extra storage.",
)

allocation_obj.resources.add(Resource.objects.get(name="Tandon"))
allocation_obj.save()

allocation_attribute_type_obj = AllocationAttributeType.objects.get(
name="slurm_account_name"
)
AllocationAttribute.objects.get_or_create(
allocation_attribute_type=allocation_attribute_type_obj,
allocation=allocation_obj,
value=f"torch_pr_{allocation_obj.project.pk}_Tandon",
)

allocation_user_obj = AllocationUser.objects.create(
allocation=allocation_obj,
user=pi1,
status=AllocationUserStatusChoice.objects.get(name="Active"),
)

# Add metered allocation
# Add Tandon allocation
allocation_obj, _ = Allocation.objects.get_or_create(
project=project_obj,
status=AllocationStatusChoice.objects.get(name="Active"),
Expand Down
Loading