diff --git a/core/views/new_hole.py b/core/views/new_hole.py index bcd0a95c..deb7fb9a 100644 --- a/core/views/new_hole.py +++ b/core/views/new_hole.py @@ -7,6 +7,9 @@ from troggle.parsers.people import who_is_this from core.position_utils import which_area # file-type import, not module type. class NewHoleForm(forms.Form): + """The validation on this form is a bit of a beast, sorry. + """ + discovery_date = forms.DateField(label="Trip date", widget=forms.DateInput(attrs={'type': 'date'}), required=True) # Identification tag_id = forms.CharField(label="New Cave Identifier for internal identifiers. Cannot easily be changed.", widget=forms.TextInput(attrs={'placeholder': @@ -23,7 +26,6 @@ class NewHoleForm(forms.Form): discoverers = forms.CharField(label="Discoverers / Investigators today", widget=forms.TextInput(attrs={'placeholder': 'e.g. Dour, Animal, Becka'}), max_length=255, required=True) - discovery_date = forms.DateField(label="Trip date", widget=forms.DateInput(attrs={'type': 'date'}), required=True) surface_wallet = forms.CharField(label="Old wallet used to find the entrance (if any)", widget=forms.TextInput(attrs={'placeholder': 'e.g. 2005 # 63'}), max_length=100, required=False) @@ -54,7 +56,7 @@ class NewHoleForm(forms.Form): dist_to_ent = forms.FloatField(label="Distance from GPS to entrance (m)", widget=forms.TextInput(attrs={'placeholder': 'e.g. 11.5'}) ) - bear_to_ent = forms.FloatField(label="Compass bearing to entrance (degrees)", + bear_to_ent = forms.FloatField(label="Compass bearing from GPS to entrance (degrees)", widget=forms.TextInput(attrs={'placeholder': 'e.g. 217'}) ) @@ -66,8 +68,8 @@ class NewHoleForm(forms.Form): photo_ent_no = forms.BooleanField(label="Entrance photos ?", required=False) photo_ent_who = forms.CharField(label="Who has photos of entrance, tag and GPS?", required=False) - who_are_you = forms.CharField(strip=True, - widget=forms.TextInput( + who_are_you = forms.CharField(strip=True, label="Who are you ? (You do not need to have been on this trip)", + widget=forms.TextInput( attrs={"size": 100, "placeholder": "You are entering data, who are you ? e.g. 'Becka' or 'Animal '", "style": "vertical-align: text-top;"} ) @@ -81,7 +83,38 @@ class NewHoleForm(forms.Form): # If a field fails basic validation (e.g., someone typed letters into a numeric field), # it won't exist in cleaned_data. .get() returns None - + def _validate_caver_list(self, field_name, year, raw_data): + """ + Helper to split comma-separated names and validate them against who_is_this. + Returns a list of validated person_ids. + """ + if not raw_data: + self._add_caver_error(field_name, "No one", year) + return [] + + # Handle both single names and comma-separated lists + names = [n.strip() for n in raw_data.split(',') if n.strip()] + validated_ids = [] + for name in names: + try: + person_id = who_is_this(year, name) + if person_id: + validated_ids.append(person_id) + else: + self._add_caver_error(field_name, name, year) + except (ValueError, IndexError) as e: + self._add_caver_error(field_name, name, year) + + return validated_ids + + def _add_caver_error(self, field_name, name, year): + """Standardized HTML error reporter""" + error_html = mark_safe( + f"'{name}' is not a recognized explorer for the year {year}. " + f"See aliases list" + ) + self.add_error(field_name, error_html) + def clean(self): # Unlike clean_, which validates one field at a time, the general clean() method # allows you to compare multiple fields against each other. @@ -115,68 +148,19 @@ class NewHoleForm(forms.Form): if wallet_id and "#" in wallet_id: year = int(clean_wallet[:4]) - camera_persons = cleaned_data.get("photo_ent_who").split(",") - discoverers = cleaned_data.get("discoverers").split(",") - gps_owner = cleaned_data.get("gps_owner") - - # 1.Check discoverers are valid people - intrepids = [] - for caver in discoverers: - caver = caver.strip() - - try: - person_id = who_is_this(year, caver) - except (ValueError, IndexError) as e: - print(f"ERROR: {caver} {repr(e)}") - person_id = None - - if person_id: - intrepids.append(person_id) - - else: - print(f"unrecognised: {caver} ") - error_html = mark_safe( - f"'{caver}' is not a recognized explorer for the year {year}. " - f"See aliases list" - ) - self.add_error('discoverers', error_html) - - # 1.Check photographer(s) are valid people - cameramen = [] - for caver in camera_persons: - - try: - person_id = who_is_this(year, caver) - except (ValueError, IndexError) as e: - print(f"ERROR: {caver} {repr(e)}") - person_id = None - - if person_id: - cameramen.append(person_id) - - else: - print(f"unrecognised: {caver} ") - error_html = mark_safe( - f"'{caver}' is not a recognized explorer for the year {year}. " - f"See aliases list" - ) - self.add_error('photo_ent_who', error_html) - - try: - person_id = who_is_this(year, gps_owner) - except (ValueError, IndexError) as e: - print(f"ERROR: {gps_owner} {repr(e)}") - person_id = None - - if person_id: - pass - else: - print(f"unrecognised: {gps_owner} ") - error_html = mark_safe( - f"'{gps_owner}' is not a recognized explorer for the year {year}. " - f"See aliases list" - ) - self.add_error('gps_owner', error_html) + intrepids = self._validate_caver_list( + 'discoverers', year, cleaned_data.get("discoverers")) + + cameramen = self._validate_caver_list( + 'photo_ent_who', year, cleaned_data.get("photo_ent_who")) + + # Even for a single name, it works fine + gps_user = self._validate_caver_list( + 'gps_owner', year, cleaned_data.get("gps_owner")) + + # can now store these lists in cleaned_data if we want + # cleaned_data['intrepid_ids'] = intrepids + # cleaned_data['cameramen_ids'] = cameramen # Entrance Photo Logic