diff --git a/integreat_cms/cms/forms/events/event_form.py b/integreat_cms/cms/forms/events/event_form.py index 3d79fcd43b..a17397076d 100644 --- a/integreat_cms/cms/forms/events/event_form.py +++ b/integreat_cms/cms/forms/events/event_form.py @@ -83,13 +83,6 @@ class Meta: widgets = { "icon": IconWidget(), } - error_messages = { - "location": { - "invalid_choice": _( - "Either disable the event location or provide a valid location" - ), - }, - } def __init__(self, **kwargs: Any) -> None: r""" @@ -131,6 +124,16 @@ def clean(self) -> dict[str, Any]: # make self.data mutable to allow values to be changed manually self.data = self.data.copy() + if not cleaned_data.get("has_not_location") and not cleaned_data.get( + "location" + ): + self.add_error( + "location", + forms.ValidationError( + _("Either disable the event location or provide a valid location"), + code="invalid_choice", + ), + ) if cleaned_data.get("is_all_day"): cleaned_data["start_time"] = time.min self.data["start_time"] = time.min diff --git a/integreat_cms/cms/views/events/event_form_view.py b/integreat_cms/cms/views/events/event_form_view.py index 58a5e748d3..14c02d6cf1 100644 --- a/integreat_cms/cms/views/events/event_form_view.py +++ b/integreat_cms/cms/views/events/event_form_view.py @@ -131,7 +131,7 @@ def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: }, ) - # pylint: disable=too-many-locals,too-many-branches + # pylint: disable=too-many-locals,too-many-branches, too-many-statements def post(self, request: HttpRequest, **kwargs: Any) -> HttpResponse: r""" Save event and ender event form for HTTP POST requests @@ -144,7 +144,6 @@ def post(self, request: HttpRequest, **kwargs: Any) -> HttpResponse: """ region = request.region language = Language.objects.get(slug=kwargs.get("language_slug")) - poi = POI.objects.filter(id=request.POST.get("location")).first() event_instance = Event.objects.filter(id=kwargs.get("event_id")).first() recurrence_rule_instance = RecurrenceRule.objects.filter( @@ -154,8 +153,19 @@ def post(self, request: HttpRequest, **kwargs: Any) -> HttpResponse: event=event_instance, language=language ).first() + data = request.POST.dict() + + if data.get("location") == "-1" or data.get("has_not_location"): + data["location"] = "" + + poi = ( + POI.objects.filter(id=data.get("location")).first() + if data.get("location") + else None + ) + event_form = EventForm( - data=request.POST, + data=data, files=request.FILES, instance=event_instance, additional_instance_attributes={"region": region, "location": poi}, diff --git a/integreat_cms/release_notes/current/unreleased/3223.yml b/integreat_cms/release_notes/current/unreleased/3223.yml new file mode 100644 index 0000000000..fcb4ca1e81 --- /dev/null +++ b/integreat_cms/release_notes/current/unreleased/3223.yml @@ -0,0 +1,2 @@ +en: Fix location check of event creation +de: Korrigiere Ortsprüfung bei der Erstellung von Veranstaltungen diff --git a/tests/cms/views/events/test_event_form.py b/tests/cms/views/events/test_event_form.py new file mode 100644 index 0000000000..da83e20606 --- /dev/null +++ b/tests/cms/views/events/test_event_form.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +import copy +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from _pytest.logging import LogCaptureFixture + from django.test.client import Client + from pytest_django.fixtures import SettingsWrapper + +import pytest +from django.test.client import Client +from django.urls import reverse + +from integreat_cms.cms.constants import status +from integreat_cms.cms.models import Event, EventTranslation +from tests.conftest import ANONYMOUS, PRIV_STAFF_ROLES, WRITE_ROLES +from tests.utils import assert_message_in_log + +REGION_SLUG = "augsburg" +POI_ID = 4 # Use a POI which belongs to the region with REGION_SLUG +EVENT_TITLE = ( + "New Event" # Choose a name that does not exist yet as event title in the test data +) + + +# (, , ) +parameters = [ + (-1, False, False), + (-1, True, True), + (POI_ID, False, True), + (POI_ID, True, True), +] + + +@pytest.mark.django_db +@pytest.mark.parametrize("parameter", parameters) +def test_create_event( + load_test_data: None, + login_role_user: tuple[Client, str], + settings: SettingsWrapper, + caplog: LogCaptureFixture, + parameter: tuple[int, bool, bool], +) -> None: + """ + Test that event creation is working as expected (focus on location check) + """ + client, role = login_role_user + poi_id, has_not_location, successfully_created = parameter + settings.LANGUAGE_CODE = "en" + + new_event = reverse( + "new_event", + kwargs={ + "region_slug": REGION_SLUG, + "language_slug": "de", + }, + ) + data = { + "title": EVENT_TITLE, + "content": "Lorem ipsum...", + "start_date": "2030-01-01", + "end_date": "2030-01-01", + "is_all_day": True, + "status": status.PUBLIC, + "location": poi_id, + } + if has_not_location: + data = copy.deepcopy(data) + data.update({"has_not_location": True}) + response = client.post( + new_event, + data=data, + ) + if role in PRIV_STAFF_ROLES + WRITE_ROLES: + response.status_code == 302 + + if successfully_created: + redirect_url = response.headers.get("location") + assert_message_in_log( + f'SUCCESS Event "{EVENT_TITLE}" was successfully created', + caplog, + ) + assert ( + f"Event "{EVENT_TITLE}" was successfully created" + in client.get(redirect_url).content.decode("utf-8") + ) + + event_translation = EventTranslation.objects.filter( + title=EVENT_TITLE + ).first() + assert event_translation + + event = Event.objects.filter(id=event_translation.event.id).first() + if poi_id == -1 or has_not_location: + assert not event.location + else: + assert event.location.id == poi_id + else: + assert_message_in_log( + "ERROR Location: Either disable the event location or provide a valid location", + caplog, + ) + assert ( + "Either disable the event location or provide a valid location" + in response.content.decode("utf-8") + ) + + event_translation = EventTranslation.objects.filter( + title=EVENT_TITLE + ).first() + assert not event_translation + + elif role == ANONYMOUS: + assert response.status_code == 302 + assert ( + response.headers.get("location") == f"{settings.LOGIN_URL}?next={new_event}" + ) + else: + assert response.status_code == 403 diff --git a/tests/cms/views/view_config.py b/tests/cms/views/view_config.py index 28626566b4..c9c351fa68 100644 --- a/tests/cms/views/view_config.py +++ b/tests/cms/views/view_config.py @@ -396,6 +396,7 @@ "end_date": "2030-01-01", "is_all_day": True, "status": status.DRAFT, + "has_not_location": True, }, ), ("new_page", STAFF_ROLES + [MANAGEMENT, EDITOR, AUTHOR, OBSERVER]), @@ -730,6 +731,7 @@ "end_date": "2030-01-01", "is_all_day": True, "status": status.DRAFT, + "has_not_location": True, }, ), ("new_page", STAFF_ROLES), @@ -1375,6 +1377,7 @@ "end_date": "2030-01-01", "is_all_day": True, "status": status.DRAFT, + "has_not_location": True, }, ), ( diff --git a/tests/mt_api/mt_api_test.py b/tests/mt_api/mt_api_test.py index 818a3acdfc..24b2cdc79f 100644 --- a/tests/mt_api/mt_api_test.py +++ b/tests/mt_api/mt_api_test.py @@ -497,6 +497,7 @@ def test_bulk_mt_up_to_date_and_ready_for_mt( "start_date": "2030-01-01", "end_date": "2030-01-01", "is_all_day": True, + "has_not_location": True, }, ), ]