feat(events): event owner and cross-club validation
Add Event.created_by (the owner, used later by the access service to let an event's creator edit it). Validate that an event's season/location/opponent — and an EventSeries' location/opponent — belong to the event's club. The teams M2M cannot be checked in clean() (M2M rows are written after save), so an m2m_changed pre_add receiver rejects teams from another club. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from datetime import timedelta
|
||||
from io import StringIO
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.management import call_command
|
||||
from django.db import IntegrityError
|
||||
from django.test import TestCase
|
||||
@@ -353,3 +354,50 @@ class ExtendSeriesCommandTests(RecurrenceTestBase):
|
||||
|
||||
self.assertEqual(series.occurrences.count(), 4)
|
||||
self.assertIn("Done.", out.getvalue())
|
||||
|
||||
|
||||
class EventClubScopeTests(EventsTestBase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.other = Club.objects.create(name="Rival FC", slug="rival-fc")
|
||||
today = timezone.localdate()
|
||||
self.other_season = Season.objects.create(club=self.other, start_date=today - timedelta(days=30), end_date=today + timedelta(days=300))
|
||||
self.other_location = Location.objects.create(club=self.other, name="Arena", address="1 St", city="Town", zip_code="1000", country="BE")
|
||||
self.other_opponent = Opponent.objects.create(club=self.other, name="Rivals")
|
||||
self.other_team = Team.objects.create(club=self.other, name="First", short_name="1")
|
||||
|
||||
def test_event_rejects_cross_club_season(self):
|
||||
event = Event(club=self.club, title="Match", start=self.future, season=self.other_season)
|
||||
with self.assertRaises(ValidationError) as ctx:
|
||||
event.full_clean()
|
||||
self.assertIn("season", ctx.exception.error_dict)
|
||||
|
||||
def test_event_rejects_cross_club_location(self):
|
||||
event = Event(club=self.club, title="Match", start=self.future, location=self.other_location)
|
||||
with self.assertRaises(ValidationError) as ctx:
|
||||
event.full_clean()
|
||||
self.assertIn("location", ctx.exception.error_dict)
|
||||
|
||||
def test_event_accepts_same_club_fields(self):
|
||||
Event(club=self.club, title="Match", start=self.future, season=self.season).full_clean()
|
||||
|
||||
def test_event_rejects_cross_club_team(self):
|
||||
event = Event.objects.create(club=self.club, title="Match", start=self.future, season=self.season)
|
||||
with self.assertRaises(ValidationError):
|
||||
event.teams.add(self.other_team)
|
||||
|
||||
def test_event_accepts_same_club_team(self):
|
||||
event = Event.objects.create(club=self.club, title="Match", start=self.future, season=self.season)
|
||||
event.teams.add(self.team)
|
||||
self.assertIn(self.team, event.teams.all())
|
||||
|
||||
def test_series_rejects_cross_club_opponent(self):
|
||||
series = EventSeries(club=self.club, title="Weekly", rrule="FREQ=WEEKLY", dtstart=self.future, opponent=self.other_opponent)
|
||||
with self.assertRaises(ValidationError) as ctx:
|
||||
series.full_clean()
|
||||
self.assertIn("opponent", ctx.exception.error_dict)
|
||||
|
||||
def test_series_rejects_cross_club_team(self):
|
||||
series = EventSeries.objects.create(club=self.club, title="Weekly", rrule="FREQ=WEEKLY", dtstart=self.future)
|
||||
with self.assertRaises(ValidationError):
|
||||
series.teams.add(self.other_team)
|
||||
|
||||
Reference in New Issue
Block a user