We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Do not allow concurrent same community roles
People should not have the same concurrent community roles.  For example if a person has an Instructor role from 2018-02-01 through 2020-06-01, any other role must end before 2018-02-01 and start after 2020-06-01.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `amy/communityroles/forms.py`
Content:
```
1 from collections import defaultdict
2 from datetime import date
3 from typing import Any, Optional, Union
4 
5 from django import forms
6 from django.core.exceptions import ObjectDoesNotExist, ValidationError
7 
8 from workshops.fields import HeavySelect2Widget, ModelSelect2Widget
9 from workshops.forms import SELECT2_SIDEBAR, BootstrapHelper, WidgetOverrideMixin
10 from workshops.models import Award, Person
11 
12 from .fields import CustomKeysJSONField
13 from .models import CommunityRole, CommunityRoleConfig, CommunityRoleInactivation
14 
15 
16 class CommunityRoleForm(WidgetOverrideMixin, forms.ModelForm):
17     class Meta:
18         model = CommunityRole
19         fields = (
20             "config",
21             "person",
22             "award",
23             "start",
24             "end",
25             "inactivation",
26             "membership",
27             "url",
28             "generic_relation_content_type",
29             "generic_relation_pk",
30         )
31         widgets = {
32             "config": HeavySelect2Widget(
33                 data_view="api:communityroleconfig-list", attrs=SELECT2_SIDEBAR
34             ),
35             "person": ModelSelect2Widget(
36                 data_view="person-lookup", attrs=SELECT2_SIDEBAR
37             ),
38             "award": ModelSelect2Widget(
39                 data_view="award-lookup", attrs=SELECT2_SIDEBAR
40             ),
41             "membership": ModelSelect2Widget(
42                 data_view="membership-lookup", attrs=SELECT2_SIDEBAR
43             ),
44             "generic_relation_content_type": forms.Select(
45                 # "disabled" means the browsers will not send the field during POST.
46                 # See how it's handled in `clean()` method below.
47                 attrs={"disabled": ""},
48             ),
49             "generic_relation_pk": HeavySelect2Widget(
50                 data_view="generic-object-lookup", attrs=SELECT2_SIDEBAR
51             ),
52         }
53         labels = {
54             "generic_relation_content_type": "Generic relation object type",
55             "generic_relation_pk": "Generic relation object",
56         }
57 
58     class Media:
59         js = ("communityrole_form.js",)
60 
61     def __init__(self, *args, **kwargs):
62         form_tag = kwargs.pop("form_tag", True)
63         super().__init__(*args, **kwargs)
64         bootstrap_kwargs = {
65             "add_cancel_button": False,
66             "form_tag": form_tag,
67         }
68         self.helper = BootstrapHelper(**bootstrap_kwargs)
69 
70     def clean(self) -> Union[dict[str, Any], None]:
71         """Validate form according to rules set up in related Community Role
72         configuration."""
73         cleaned_data = super().clean()
74         if not cleaned_data:
75             return cleaned_data
76 
77         errors: defaultdict[str, list[ValidationError]] = defaultdict(list)
78         config: Optional[CommunityRoleConfig] = cleaned_data.get("config")
79         award: Optional[Award] = cleaned_data.get("award")
80         person: Optional[Person] = cleaned_data.get("person")
81         inactivation: Optional[CommunityRoleInactivation] = cleaned_data.get(
82             "inactivation"
83         )
84         end_date: Optional[date] = cleaned_data.get("end")
85 
86         # Config is required, but field validation for 'config' should raise
87         # validation error first.
88         if not config:
89             return cleaned_data
90 
91         # Award required?
92         if config.link_to_award and not award:
93             errors["award"].append(
94                 ValidationError(f"Award is required with community role {config}")
95             )
96 
97         # Award should point at the same person the community role links to
98         if award and award.person != person:
99             errors["award"].append(ValidationError(f"Award should belong to {person}"))
100 
101         # Specific award badge required?
102         if (badge := config.award_badge_limit) and award:
103             if award.badge != badge:
104                 errors["award"].append(
105                     ValidationError(
106                         f"Award badge must be {badge} for community role {config}"
107                     )
108                 )
109 
110         # Membership required?
111         if config.link_to_membership and not cleaned_data.get("membership"):
112             errors["membership"].append(
113                 ValidationError(f"Membership is required with community role {config}")
114             )
115 
116         # Additional URL supported?
117         if not config.additional_url and cleaned_data.get("url"):
118             errors["url"].append(
119                 ValidationError(f"URL is not supported for community role {config}")
120             )
121 
122         # Widget for `generic_relation_content_type` is disabled in HTML, which
123         # makes browsers not send it. The code below sets the default value to
124         # the same value as in related config.
125         generic_relation_content_type = config.generic_relation_content_type
126 
127         # Generic relation object must exist
128         if config.generic_relation_content_type and generic_relation_content_type:
129             model_class = generic_relation_content_type.model_class()
130             try:
131                 model_class._base_manager.get(
132                     pk=cleaned_data.get("generic_relation_pk")
133                 )
134             except ObjectDoesNotExist:
135                 errors["generic_relation_pk"].append(
136                     ValidationError(
137                         f"Generic relation object of model {model_class.__name__} "
138                         "doesn't exist"
139                     )
140                 )
141 
142         # End date is required when any inactivation was selected.
143         if inactivation is not None and end_date is None:
144             errors["end"].append(
145                 ValidationError("Required when Reason for inactivation selected.")
146             )
147 
148         if errors:
149             raise ValidationError(errors)
150 
151         return cleaned_data
152 
153     def clean_end(self):
154         """Validate that end >= start"""
155         start = self.cleaned_data.get("start")
156         end = self.cleaned_data.get("end")
157         if start and end and end < start:
158             raise ValidationError("Must not be earlier than start date.")
159         return end
160 
161 
162 class CommunityRoleUpdateForm(CommunityRoleForm):
163     config = forms.ModelChoiceField(
164         queryset=CommunityRoleConfig.objects.all(),
165         disabled=True,
166     )
167 
168     custom_keys = CustomKeysJSONField(required=False)
169 
170     class Meta(CommunityRoleForm.Meta):
171         fields = CommunityRoleForm.Meta.fields + ("custom_keys",)
172 
173     def __init__(self, *args, community_role_config: CommunityRoleConfig, **kwargs):
174         self.config = community_role_config
175         super().__init__(*args, **kwargs)
176         self.fields["custom_keys"].apply_labels(self.config.custom_key_labels)
177
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/amy/communityroles/forms.py b/amy/communityroles/forms.py
--- a/amy/communityroles/forms.py
+++ b/amy/communityroles/forms.py
@@ -4,6 +4,7 @@
 
 from django import forms
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
+from django.db.models import Q
 
 from workshops.fields import HeavySelect2Widget, ModelSelect2Widget
 from workshops.forms import SELECT2_SIDEBAR, BootstrapHelper, WidgetOverrideMixin
@@ -81,11 +82,12 @@
         inactivation: Optional[CommunityRoleInactivation] = cleaned_data.get(
             "inactivation"
         )
+        start_date: Optional[date] = cleaned_data.get("start")
         end_date: Optional[date] = cleaned_data.get("end")
 
         # Config is required, but field validation for 'config' should raise
         # validation error first.
-        if not config:
+        if not config or not person:
             return cleaned_data
 
         # Award required?
@@ -145,8 +147,13 @@
                 ValidationError("Required when Reason for inactivation selected.")
             )
 
+        try:
+            self.check_concurrent_role(config, person, start_date, end_date)
+        except ValidationError as exc:
+            errors["person"].append(exc)
+
         if errors:
-            raise ValidationError(errors)
+            raise ValidationError(errors)  # type: ignore
 
         return cleaned_data
 
@@ -158,6 +165,32 @@
             raise ValidationError("Must not be earlier than start date.")
         return end
 
+    def check_concurrent_role(
+        self,
+        config: Optional[CommunityRoleConfig] = None,
+        person: Optional[Person] = None,
+        start_date: Optional[date] = None,
+        end_date: Optional[date] = None,
+    ) -> Optional[Person]:
+        """Person should not have any concurrent Community Roles of the same type in the
+        same time."""
+        # These are required fields in the form, so they should be present.
+        if config and person and start_date:
+            same_time = Q(end__gt=start_date) | Q(end__isnull=True)
+            if end_date:
+                # if `end_date` is present, introduce additional condition
+                same_time &= Q(start__lt=end_date) | Q(start__isnull=True)
+            if roles := CommunityRole.objects.filter(
+                person=person, config=config
+            ).filter(same_time):
+                raise (
+                    ValidationError(
+                        f"Person {person} has concurrent community roles: "
+                        f"{list(roles)}."
+                    )
+                )
+        return person
+
 
 class CommunityRoleUpdateForm(CommunityRoleForm):
     config = forms.ModelChoiceField(
@@ -173,4 +206,16 @@
     def __init__(self, *args, community_role_config: CommunityRoleConfig, **kwargs):
         self.config = community_role_config
         super().__init__(*args, **kwargs)
-        self.fields["custom_keys"].apply_labels(self.config.custom_key_labels)
+        self.fields["custom_keys"].apply_labels(  # type: ignore
+            self.config.custom_key_labels
+        )
+
+    def check_concurrent_role(
+        self,
+        config: Optional[CommunityRoleConfig] = None,
+        person: Optional[Person] = None,
+        start_date: Optional[date] = None,
+        end_date: Optional[date] = None,
+    ) -> Optional[Person]:
+        """When updating a CommunityRole, we shouldn't check for concurrent roles."""
+        return person

{"golden_diff": "diff --git a/amy/communityroles/forms.py b/amy/communityroles/forms.py\n--- a/amy/communityroles/forms.py\n+++ b/amy/communityroles/forms.py\n@@ -4,6 +4,7 @@\n \n from django import forms\n from django.core.exceptions import ObjectDoesNotExist, ValidationError\n+from django.db.models import Q\n \n from workshops.fields import HeavySelect2Widget, ModelSelect2Widget\n from workshops.forms import SELECT2_SIDEBAR, BootstrapHelper, WidgetOverrideMixin\n@@ -81,11 +82,12 @@\n         inactivation: Optional[CommunityRoleInactivation] = cleaned_data.get(\n             \"inactivation\"\n         )\n+        start_date: Optional[date] = cleaned_data.get(\"start\")\n         end_date: Optional[date] = cleaned_data.get(\"end\")\n \n         # Config is required, but field validation for 'config' should raise\n         # validation error first.\n-        if not config:\n+        if not config or not person:\n             return cleaned_data\n \n         # Award required?\n@@ -145,8 +147,13 @@\n                 ValidationError(\"Required when Reason for inactivation selected.\")\n             )\n \n+        try:\n+            self.check_concurrent_role(config, person, start_date, end_date)\n+        except ValidationError as exc:\n+            errors[\"person\"].append(exc)\n+\n         if errors:\n-            raise ValidationError(errors)\n+            raise ValidationError(errors)  # type: ignore\n \n         return cleaned_data\n \n@@ -158,6 +165,32 @@\n             raise ValidationError(\"Must not be earlier than start date.\")\n         return end\n \n+    def check_concurrent_role(\n+        self,\n+        config: Optional[CommunityRoleConfig] = None,\n+        person: Optional[Person] = None,\n+        start_date: Optional[date] = None,\n+        end_date: Optional[date] = None,\n+    ) -> Optional[Person]:\n+        \"\"\"Person should not have any concurrent Community Roles of the same type in the\n+        same time.\"\"\"\n+        # These are required fields in the form, so they should be present.\n+        if config and person and start_date:\n+            same_time = Q(end__gt=start_date) | Q(end__isnull=True)\n+            if end_date:\n+                # if `end_date` is present, introduce additional condition\n+                same_time &= Q(start__lt=end_date) | Q(start__isnull=True)\n+            if roles := CommunityRole.objects.filter(\n+                person=person, config=config\n+            ).filter(same_time):\n+                raise (\n+                    ValidationError(\n+                        f\"Person {person} has concurrent community roles: \"\n+                        f\"{list(roles)}.\"\n+                    )\n+                )\n+        return person\n+\n \n class CommunityRoleUpdateForm(CommunityRoleForm):\n     config = forms.ModelChoiceField(\n@@ -173,4 +206,16 @@\n     def __init__(self, *args, community_role_config: CommunityRoleConfig, **kwargs):\n         self.config = community_role_config\n         super().__init__(*args, **kwargs)\n-        self.fields[\"custom_keys\"].apply_labels(self.config.custom_key_labels)\n+        self.fields[\"custom_keys\"].apply_labels(  # type: ignore\n+            self.config.custom_key_labels\n+        )\n+\n+    def check_concurrent_role(\n+        self,\n+        config: Optional[CommunityRoleConfig] = None,\n+        person: Optional[Person] = None,\n+        start_date: Optional[date] = None,\n+        end_date: Optional[date] = None,\n+    ) -> Optional[Person]:\n+        \"\"\"When updating a CommunityRole, we shouldn't check for concurrent roles.\"\"\"\n+        return person\n", "issue": "Do not allow concurrent same community roles\nPeople should not have the same concurrent community roles.  For example if a person has an Instructor role from 2018-02-01 through 2020-06-01, any other role must end before 2018-02-01 and start after 2020-06-01.\n", "before_files": [{"content": "from collections import defaultdict\nfrom datetime import date\nfrom typing import Any, Optional, Union\n\nfrom django import forms\nfrom django.core.exceptions import ObjectDoesNotExist, ValidationError\n\nfrom workshops.fields import HeavySelect2Widget, ModelSelect2Widget\nfrom workshops.forms import SELECT2_SIDEBAR, BootstrapHelper, WidgetOverrideMixin\nfrom workshops.models import Award, Person\n\nfrom .fields import CustomKeysJSONField\nfrom .models import CommunityRole, CommunityRoleConfig, CommunityRoleInactivation\n\n\nclass CommunityRoleForm(WidgetOverrideMixin, forms.ModelForm):\n    class Meta:\n        model = CommunityRole\n        fields = (\n            \"config\",\n            \"person\",\n            \"award\",\n            \"start\",\n            \"end\",\n            \"inactivation\",\n            \"membership\",\n            \"url\",\n            \"generic_relation_content_type\",\n            \"generic_relation_pk\",\n        )\n        widgets = {\n            \"config\": HeavySelect2Widget(\n                data_view=\"api:communityroleconfig-list\", attrs=SELECT2_SIDEBAR\n            ),\n            \"person\": ModelSelect2Widget(\n                data_view=\"person-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"award\": ModelSelect2Widget(\n                data_view=\"award-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"membership\": ModelSelect2Widget(\n                data_view=\"membership-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"generic_relation_content_type\": forms.Select(\n                # \"disabled\" means the browsers will not send the field during POST.\n                # See how it's handled in `clean()` method below.\n                attrs={\"disabled\": \"\"},\n            ),\n            \"generic_relation_pk\": HeavySelect2Widget(\n                data_view=\"generic-object-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n        }\n        labels = {\n            \"generic_relation_content_type\": \"Generic relation object type\",\n            \"generic_relation_pk\": \"Generic relation object\",\n        }\n\n    class Media:\n        js = (\"communityrole_form.js\",)\n\n    def __init__(self, *args, **kwargs):\n        form_tag = kwargs.pop(\"form_tag\", True)\n        super().__init__(*args, **kwargs)\n        bootstrap_kwargs = {\n            \"add_cancel_button\": False,\n            \"form_tag\": form_tag,\n        }\n        self.helper = BootstrapHelper(**bootstrap_kwargs)\n\n    def clean(self) -> Union[dict[str, Any], None]:\n        \"\"\"Validate form according to rules set up in related Community Role\n        configuration.\"\"\"\n        cleaned_data = super().clean()\n        if not cleaned_data:\n            return cleaned_data\n\n        errors: defaultdict[str, list[ValidationError]] = defaultdict(list)\n        config: Optional[CommunityRoleConfig] = cleaned_data.get(\"config\")\n        award: Optional[Award] = cleaned_data.get(\"award\")\n        person: Optional[Person] = cleaned_data.get(\"person\")\n        inactivation: Optional[CommunityRoleInactivation] = cleaned_data.get(\n            \"inactivation\"\n        )\n        end_date: Optional[date] = cleaned_data.get(\"end\")\n\n        # Config is required, but field validation for 'config' should raise\n        # validation error first.\n        if not config:\n            return cleaned_data\n\n        # Award required?\n        if config.link_to_award and not award:\n            errors[\"award\"].append(\n                ValidationError(f\"Award is required with community role {config}\")\n            )\n\n        # Award should point at the same person the community role links to\n        if award and award.person != person:\n            errors[\"award\"].append(ValidationError(f\"Award should belong to {person}\"))\n\n        # Specific award badge required?\n        if (badge := config.award_badge_limit) and award:\n            if award.badge != badge:\n                errors[\"award\"].append(\n                    ValidationError(\n                        f\"Award badge must be {badge} for community role {config}\"\n                    )\n                )\n\n        # Membership required?\n        if config.link_to_membership and not cleaned_data.get(\"membership\"):\n            errors[\"membership\"].append(\n                ValidationError(f\"Membership is required with community role {config}\")\n            )\n\n        # Additional URL supported?\n        if not config.additional_url and cleaned_data.get(\"url\"):\n            errors[\"url\"].append(\n                ValidationError(f\"URL is not supported for community role {config}\")\n            )\n\n        # Widget for `generic_relation_content_type` is disabled in HTML, which\n        # makes browsers not send it. The code below sets the default value to\n        # the same value as in related config.\n        generic_relation_content_type = config.generic_relation_content_type\n\n        # Generic relation object must exist\n        if config.generic_relation_content_type and generic_relation_content_type:\n            model_class = generic_relation_content_type.model_class()\n            try:\n                model_class._base_manager.get(\n                    pk=cleaned_data.get(\"generic_relation_pk\")\n                )\n            except ObjectDoesNotExist:\n                errors[\"generic_relation_pk\"].append(\n                    ValidationError(\n                        f\"Generic relation object of model {model_class.__name__} \"\n                        \"doesn't exist\"\n                    )\n                )\n\n        # End date is required when any inactivation was selected.\n        if inactivation is not None and end_date is None:\n            errors[\"end\"].append(\n                ValidationError(\"Required when Reason for inactivation selected.\")\n            )\n\n        if errors:\n            raise ValidationError(errors)\n\n        return cleaned_data\n\n    def clean_end(self):\n        \"\"\"Validate that end >= start\"\"\"\n        start = self.cleaned_data.get(\"start\")\n        end = self.cleaned_data.get(\"end\")\n        if start and end and end < start:\n            raise ValidationError(\"Must not be earlier than start date.\")\n        return end\n\n\nclass CommunityRoleUpdateForm(CommunityRoleForm):\n    config = forms.ModelChoiceField(\n        queryset=CommunityRoleConfig.objects.all(),\n        disabled=True,\n    )\n\n    custom_keys = CustomKeysJSONField(required=False)\n\n    class Meta(CommunityRoleForm.Meta):\n        fields = CommunityRoleForm.Meta.fields + (\"custom_keys\",)\n\n    def __init__(self, *args, community_role_config: CommunityRoleConfig, **kwargs):\n        self.config = community_role_config\n        super().__init__(*args, **kwargs)\n        self.fields[\"custom_keys\"].apply_labels(self.config.custom_key_labels)\n", "path": "amy/communityroles/forms.py"}], "after_files": [{"content": "from collections import defaultdict\nfrom datetime import date\nfrom typing import Any, Optional, Union\n\nfrom django import forms\nfrom django.core.exceptions import ObjectDoesNotExist, ValidationError\nfrom django.db.models import Q\n\nfrom workshops.fields import HeavySelect2Widget, ModelSelect2Widget\nfrom workshops.forms import SELECT2_SIDEBAR, BootstrapHelper, WidgetOverrideMixin\nfrom workshops.models import Award, Person\n\nfrom .fields import CustomKeysJSONField\nfrom .models import CommunityRole, CommunityRoleConfig, CommunityRoleInactivation\n\n\nclass CommunityRoleForm(WidgetOverrideMixin, forms.ModelForm):\n    class Meta:\n        model = CommunityRole\n        fields = (\n            \"config\",\n            \"person\",\n            \"award\",\n            \"start\",\n            \"end\",\n            \"inactivation\",\n            \"membership\",\n            \"url\",\n            \"generic_relation_content_type\",\n            \"generic_relation_pk\",\n        )\n        widgets = {\n            \"config\": HeavySelect2Widget(\n                data_view=\"api:communityroleconfig-list\", attrs=SELECT2_SIDEBAR\n            ),\n            \"person\": ModelSelect2Widget(\n                data_view=\"person-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"award\": ModelSelect2Widget(\n                data_view=\"award-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"membership\": ModelSelect2Widget(\n                data_view=\"membership-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n            \"generic_relation_content_type\": forms.Select(\n                # \"disabled\" means the browsers will not send the field during POST.\n                # See how it's handled in `clean()` method below.\n                attrs={\"disabled\": \"\"},\n            ),\n            \"generic_relation_pk\": HeavySelect2Widget(\n                data_view=\"generic-object-lookup\", attrs=SELECT2_SIDEBAR\n            ),\n        }\n        labels = {\n            \"generic_relation_content_type\": \"Generic relation object type\",\n            \"generic_relation_pk\": \"Generic relation object\",\n        }\n\n    class Media:\n        js = (\"communityrole_form.js\",)\n\n    def __init__(self, *args, **kwargs):\n        form_tag = kwargs.pop(\"form_tag\", True)\n        super().__init__(*args, **kwargs)\n        bootstrap_kwargs = {\n            \"add_cancel_button\": False,\n            \"form_tag\": form_tag,\n        }\n        self.helper = BootstrapHelper(**bootstrap_kwargs)\n\n    def clean(self) -> Union[dict[str, Any], None]:\n        \"\"\"Validate form according to rules set up in related Community Role\n        configuration.\"\"\"\n        cleaned_data = super().clean()\n        if not cleaned_data:\n            return cleaned_data\n\n        errors: defaultdict[str, list[ValidationError]] = defaultdict(list)\n        config: Optional[CommunityRoleConfig] = cleaned_data.get(\"config\")\n        award: Optional[Award] = cleaned_data.get(\"award\")\n        person: Optional[Person] = cleaned_data.get(\"person\")\n        inactivation: Optional[CommunityRoleInactivation] = cleaned_data.get(\n            \"inactivation\"\n        )\n        start_date: Optional[date] = cleaned_data.get(\"start\")\n        end_date: Optional[date] = cleaned_data.get(\"end\")\n\n        # Config is required, but field validation for 'config' should raise\n        # validation error first.\n        if not config or not person:\n            return cleaned_data\n\n        # Award required?\n        if config.link_to_award and not award:\n            errors[\"award\"].append(\n                ValidationError(f\"Award is required with community role {config}\")\n            )\n\n        # Award should point at the same person the community role links to\n        if award and award.person != person:\n            errors[\"award\"].append(ValidationError(f\"Award should belong to {person}\"))\n\n        # Specific award badge required?\n        if (badge := config.award_badge_limit) and award:\n            if award.badge != badge:\n                errors[\"award\"].append(\n                    ValidationError(\n                        f\"Award badge must be {badge} for community role {config}\"\n                    )\n                )\n\n        # Membership required?\n        if config.link_to_membership and not cleaned_data.get(\"membership\"):\n            errors[\"membership\"].append(\n                ValidationError(f\"Membership is required with community role {config}\")\n            )\n\n        # Additional URL supported?\n        if not config.additional_url and cleaned_data.get(\"url\"):\n            errors[\"url\"].append(\n                ValidationError(f\"URL is not supported for community role {config}\")\n            )\n\n        # Widget for `generic_relation_content_type` is disabled in HTML, which\n        # makes browsers not send it. The code below sets the default value to\n        # the same value as in related config.\n        generic_relation_content_type = config.generic_relation_content_type\n\n        # Generic relation object must exist\n        if config.generic_relation_content_type and generic_relation_content_type:\n            model_class = generic_relation_content_type.model_class()\n            try:\n                model_class._base_manager.get(\n                    pk=cleaned_data.get(\"generic_relation_pk\")\n                )\n            except ObjectDoesNotExist:\n                errors[\"generic_relation_pk\"].append(\n                    ValidationError(\n                        f\"Generic relation object of model {model_class.__name__} \"\n                        \"doesn't exist\"\n                    )\n                )\n\n        # End date is required when any inactivation was selected.\n        if inactivation is not None and end_date is None:\n            errors[\"end\"].append(\n                ValidationError(\"Required when Reason for inactivation selected.\")\n            )\n\n        try:\n            self.check_concurrent_role(config, person, start_date, end_date)\n        except ValidationError as exc:\n            errors[\"person\"].append(exc)\n\n        if errors:\n            raise ValidationError(errors)  # type: ignore\n\n        return cleaned_data\n\n    def clean_end(self):\n        \"\"\"Validate that end >= start\"\"\"\n        start = self.cleaned_data.get(\"start\")\n        end = self.cleaned_data.get(\"end\")\n        if start and end and end < start:\n            raise ValidationError(\"Must not be earlier than start date.\")\n        return end\n\n    def check_concurrent_role(\n        self,\n        config: Optional[CommunityRoleConfig] = None,\n        person: Optional[Person] = None,\n        start_date: Optional[date] = None,\n        end_date: Optional[date] = None,\n    ) -> Optional[Person]:\n        \"\"\"Person should not have any concurrent Community Roles of the same type in the\n        same time.\"\"\"\n        # These are required fields in the form, so they should be present.\n        if config and person and start_date:\n            same_time = Q(end__gt=start_date) | Q(end__isnull=True)\n            if end_date:\n                # if `end_date` is present, introduce additional condition\n                same_time &= Q(start__lt=end_date) | Q(start__isnull=True)\n            if roles := CommunityRole.objects.filter(\n                person=person, config=config\n            ).filter(same_time):\n                raise (\n                    ValidationError(\n                        f\"Person {person} has concurrent community roles: \"\n                        f\"{list(roles)}.\"\n                    )\n                )\n        return person\n\n\nclass CommunityRoleUpdateForm(CommunityRoleForm):\n    config = forms.ModelChoiceField(\n        queryset=CommunityRoleConfig.objects.all(),\n        disabled=True,\n    )\n\n    custom_keys = CustomKeysJSONField(required=False)\n\n    class Meta(CommunityRoleForm.Meta):\n        fields = CommunityRoleForm.Meta.fields + (\"custom_keys\",)\n\n    def __init__(self, *args, community_role_config: CommunityRoleConfig, **kwargs):\n        self.config = community_role_config\n        super().__init__(*args, **kwargs)\n        self.fields[\"custom_keys\"].apply_labels(  # type: ignore\n            self.config.custom_key_labels\n        )\n\n    def check_concurrent_role(\n        self,\n        config: Optional[CommunityRoleConfig] = None,\n        person: Optional[Person] = None,\n        start_date: Optional[date] = None,\n        end_date: Optional[date] = None,\n    ) -> Optional[Person]:\n        \"\"\"When updating a CommunityRole, we shouldn't check for concurrent roles.\"\"\"\n        return person\n", "path": "amy/communityroles/forms.py"}]}