Skip to content
Merged
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
24 changes: 24 additions & 0 deletions src/apps/api/tests/test_submissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ def setUp(self):
self.leaderboard = LeaderboardFactory()
self.comp = CompetitionFactory(created_by=self.creator)
self.phase = PhaseFactory(competition=self.comp)
self.organization = OrganizationFactory()

# Approved participant
CompetitionParticipantFactory(user=self.participant, competition=self.comp, status=CompetitionParticipant.APPROVED)
Expand Down Expand Up @@ -591,6 +592,15 @@ def setUp(self):
leaderboard=None
)

self.organization_submission = SubmissionFactory(
phase=self.phase,
owner=self.participant,
status=Submission.FINISHED,
is_soft_deleted=False,
leaderboard=None,
organization=self.organization
)

def test_cannot_delete_submission_if_not_owner(self):
"""Ensure that a non-owner cannot soft delete a submission."""
self.client.login(username="other_user", password="other")
Expand Down Expand Up @@ -639,3 +649,17 @@ def test_can_soft_delete_submission_successfully(self):
# Refresh from DB to verify
self.submission.refresh_from_db()
assert self.submission.is_soft_deleted is True

def test_organization_is_removed_from_soft_deleted_submission(self):
"""Ensure a organization reference is removed from soft-deleted submission"""
self.client.login(username="participant", password="participant")
url = reverse("submission-soft-delete", args=[self.organization_submission.pk])
resp = self.client.delete(url)

assert resp.status_code == 200
assert resp.data["message"] == "Submission deleted successfully"

# Refresh from DB to verify
self.organization_submission.refresh_from_db()
assert self.organization_submission.is_soft_deleted is True
assert self.organization_submission.organization is None
22 changes: 15 additions & 7 deletions src/apps/api/views/profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from rest_framework.response import Response
from rest_framework import status
from django.urls import reverse
from django.db import IntegrityError

from api.permissions import IsUserAdminOrIsSelf, IsOrganizationEditor
from api.serializers.profiles import MyProfileSerializer, UserSerializer, \
Expand Down Expand Up @@ -257,17 +258,24 @@ def delete_organization(self, request, pk=None):
try:
org = Organization.objects.get(id=pk)
member = org.membership_set.get(user=request.user)
if member.group == Membership.OWNER:
org.delete()
return Response({
"success": True,
"message": "Organization deleted!"
})
else:
if member.group != Membership.OWNER:
return Response({
"success": False,
"message": "You do not have delete rights!"
})

org.delete()
return Response({
"success": True,
"message": "Organization deleted!"
})

except IntegrityError:
return Response({
"success": False,
"message": "This organization cannot be deleted because it is associated with existing submissions. Please remove those submissions first."
})

except Exception as e:
return Response({
"success": False,
Expand Down
4 changes: 4 additions & 0 deletions src/apps/competitions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ def soft_delete(self):
"""
Soft delete the submission: remove files but keep record in DB.
Also deletes associated SubmissionDetails and cleans up storage.
Also removes organization reference from the submission
"""

# Remove related files from storage
Expand All @@ -600,6 +601,9 @@ def soft_delete(self):
# Clear the data field for this submission
self.data = None

# Clear the organization field for this submission
self.organization = None

# Mark submission as deleted
self.is_soft_deleted = True
self.soft_deleted_when = now()
Expand Down