diff --git a/backend/clubs/management/commands/merge_duplicate_committees.py b/backend/clubs/management/commands/merge_duplicate_committees.py deleted file mode 100644 index ba3b9aa81..000000000 --- a/backend/clubs/management/commands/merge_duplicate_committees.py +++ /dev/null @@ -1,91 +0,0 @@ -import logging - -from django.core.management.base import BaseCommand -from django.db import transaction -from django.db.models import Count - -from clubs.models import ApplicationCommittee - - -logger = logging.getLogger(__name__) - - -class Command(BaseCommand): - help = "Merges committees with duplicate names within the same application" - web_execute = True - - def add_arguments(self, parser): - parser.add_argument( - "--dry-run", - action="store_true", - help="Run without making any changes", - ) - - def handle(self, *args, **options): - dry_run = options["dry_run"] - - try: - with transaction.atomic(): - # Find committees that have the same name within an application - duplicate_committees = ( - ApplicationCommittee.objects.values("name", "application") - .annotate(count=Count("id")) - .filter(count__gt=1) - ) - - for duplicate in duplicate_committees: - name = duplicate["name"] - application_id = duplicate["application"] - - committees = ApplicationCommittee.objects.filter( - name=name, application=application_id - ).order_by("id") - - primary_committee = committees.first() - if not primary_committee: - continue - - logger.info( - f"Processing duplicate committees with name '{name}' " - f"in application {application_id}" - ) - - # Merge all other committees into the primary one - for committee in committees[1:]: - try: - if not dry_run: - # Reassign questions to primary committee - questions_moved = ( - committee.applicationquestion_set.update( - committees=primary_committee - ) - ) - committee.delete() - - logger.info( - f"Moved {questions_moved} questions from committee " - f"{committee.id} to {primary_committee.id}" - ) - else: - logger.info( - f"[DRY RUN] Would move questions from committee " - f"{committee.id} to {primary_committee.id}" - ) - - except Exception as e: - logger.error( - f"Failed to merge committee {committee.id} into " - f"{primary_committee.id}: {str(e)}" - ) - raise - - if dry_run: - logger.info("Dry run completed - rolling back") - raise Exception("Dry run completed - rolling back") - else: - logger.info("Successfully merged duplicate committees") - - except Exception as e: - if not dry_run: - logger.error(f"Failed: {str(e)}") - raise diff --git a/backend/clubs/serializers.py b/backend/clubs/serializers.py index 59f04ab59..fc9f1a095 100644 --- a/backend/clubs/serializers.py +++ b/backend/clubs/serializers.py @@ -2855,12 +2855,6 @@ def save(self): ) ) ) - - # Committee names must be unique - normalized_committees = [name.strip().lower() for name in committees] - if len(set(normalized_committees)) != len(normalized_committees): - raise serializers.ValidationError("Committee names must be unique") - if prev_committee_names != committees: if application_obj.application_start_time < now: raise serializers.ValidationError( diff --git a/backend/tests/clubs/test_views.py b/backend/tests/clubs/test_views.py index 41c2995de..b4931d737 100644 --- a/backend/tests/clubs/test_views.py +++ b/backend/tests/clubs/test_views.py @@ -19,7 +19,6 @@ from clubs.filters import DEFAULT_PAGE_SIZE from clubs.models import ( Advisor, - ApplicationCommittee, ApplicationSubmission, Asset, Badge, @@ -2938,54 +2937,6 @@ def test_club_approval_response_templates(self): ) self.assertEqual(resp.status_code, 403) - def test_application_duplicate_committees(self): - """ - Test that duplicate committees are rejected when creating/updating applications. - """ - date = datetime.datetime.now() + datetime.timedelta(days=1) - - self.client.login(username=self.user5.username, password="test") - - # Test creating new application with duplicates - response = self.client.post( - reverse("club-applications-list", args=(self.club1.code,)), - data={ - "name": "Test Application", - "application_start_time": date, - "application_end_time": date + datetime.timedelta(days=7), - "result_release_time": date + datetime.timedelta(days=14), - "committees": [{"name": "General Member"}, {"name": "General Member"}], - }, - content_type="application/json", - ) - - self.assertEqual(response.status_code, 400) - self.assertIn("Committee names must be unique", str(response.content)) - - # Create valid application for patch test - application = ClubApplication.objects.create( - name="Test Application", - club=self.club1, - application_start_time=date, - application_end_time=date + datetime.timedelta(days=7), - result_release_time=date + datetime.timedelta(days=14), - ) - ApplicationCommittee.objects.create( - name="General Member", application=application - ) - - # Try to update with duplicate committees - response = self.client.patch( - reverse("club-applications-detail", args=(self.club1.code, application.id)), - data={ - "committees": [{"name": "General Member"}, {"name": "General Member"}] - }, - content_type="application/json", - ) - - self.assertEqual(response.status_code, 400) - self.assertIn("Committee names must be unique", str(response.content)) - class HealthTestCase(TestCase): def test_health(self):