From 37a2fb6a938d3317af52c0a4e4b9a4799e0af243 Mon Sep 17 00:00:00 2001 From: Thomas Steen Rasmussen Date: Tue, 10 Mar 2020 19:45:23 +0100 Subject: [PATCH] make entering a DECT phonenumber optional if letters were entered, and handle lowercase letters better --- src/phonebook/dectutils.py | 2 +- .../migrations/0003_auto_20200310_1923.py | 31 +++++++++++++++++++ src/phonebook/models.py | 27 +++++++++++----- src/phonebook/views.py | 20 ++++++------ 4 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 src/phonebook/migrations/0003_auto_20200310_1923.py diff --git a/src/phonebook/dectutils.py b/src/phonebook/dectutils.py index 957fb330..ef17d528 100644 --- a/src/phonebook/dectutils.py +++ b/src/phonebook/dectutils.py @@ -51,5 +51,5 @@ class DectUtils: """ result = "" for letter in letters: - result += self.REVERSE_DECT_MATRIX[letter] + result += self.REVERSE_DECT_MATRIX[letter.upper()] return result diff --git a/src/phonebook/migrations/0003_auto_20200310_1923.py b/src/phonebook/migrations/0003_auto_20200310_1923.py new file mode 100644 index 00000000..572d1fc1 --- /dev/null +++ b/src/phonebook/migrations/0003_auto_20200310_1923.py @@ -0,0 +1,31 @@ +# Generated by Django 3.0.3 on 2020-03-10 18:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("phonebook", "0002_auto_20200310_1902"), + ] + + operations = [ + migrations.AlterField( + model_name="dectregistration", + name="letters", + field=models.CharField( + blank=True, + help_text="The letters or numbers chosen to represent this DECT number in the phonebook. Optional if you specify a number.", + max_length=9, + ), + ), + migrations.AlterField( + model_name="dectregistration", + name="number", + field=models.CharField( + blank=True, + help_text="The DECT phonenumber, four digits or more. Optional if you specify letters.", + max_length=9, + ), + ), + ] diff --git a/src/phonebook/models.py b/src/phonebook/models.py index 3e4147cf..fb982786 100644 --- a/src/phonebook/models.py +++ b/src/phonebook/models.py @@ -8,6 +8,7 @@ from utils.models import CampRelatedModel from .dectutils import DectUtils logger = logging.getLogger("bornhack.%s" % __name__) +dectutil = DectUtils() class DectRegistration(CampRelatedModel): @@ -29,13 +30,15 @@ class DectRegistration(CampRelatedModel): ) number = models.CharField( - max_length=9, help_text="The DECT phonenumber, four digits or more.", + max_length=9, + blank=True, + help_text="The DECT phonenumber, four digits or more. Optional if you specify letters.", ) letters = models.CharField( max_length=9, blank=True, - help_text="The letters or numbers chosen to represent this DECT number in the phonebook. Optional.", + help_text="The letters or numbers chosen to represent this DECT number in the phonebook. Optional if you specify a number.", ) description = models.TextField( @@ -55,6 +58,7 @@ class DectRegistration(CampRelatedModel): """ This is just here so we get the validation in the admin as well. """ + # validate that the phonenumber and letters are valid and then save() self.clean_number() self.clean_letters() super().save(*args, **kwargs) @@ -65,6 +69,16 @@ class DectRegistration(CampRelatedModel): This code really belongs in model.clean(), but that gets called before form_valid() which is where we set the Camp object for the model instance. """ + # first check if we have a phonenumber... + if not self.number: + # we have no phonenumber, do we have some letters at least? + if not self.letters: + raise ValidationError( + "You must enter either a phonenumber or a letter representation of the phonenumber!" + ) + # we have letters but not a number, let's deduce the numbers + self.number = dectutil.letters_to_number(self.letters) + # First of all, check that number is numeric try: int(self.number) @@ -77,7 +91,7 @@ class DectRegistration(CampRelatedModel): .exclude(pk=self.pk) .exists() ): - raise ValidationError("This DECT number is in use") + raise ValidationError(f"The DECT number {self.number} is in use") # check for conflicts with a longer number if ( @@ -88,7 +102,7 @@ class DectRegistration(CampRelatedModel): .exists() ): raise ValidationError( - "This DECT number is not available, it conflicts with a longer number." + f"The DECT number {self.number} is not available, it conflicts with a longer number." ) # check if a shorter number is blocking @@ -100,7 +114,7 @@ class DectRegistration(CampRelatedModel): .exists() ): raise ValidationError( - "This DECT number is not available, it conflicts with a shorter number." + f"The DECT number {self.number} is not available, it conflicts with a shorter number." ) i -= 1 @@ -118,14 +132,13 @@ class DectRegistration(CampRelatedModel): ) # loop over the digits in the phonenumber - dectutil = DectUtils() combinations = list(dectutil.get_dect_letter_combinations(self.number)) if not combinations: raise ValidationError( "Numbers with 0 and 1 in them can not be expressed as letters" ) - if self.letters not in list(combinations): + if self.letters.upper() not in list(combinations): # something is fucky, loop over letters to give a better error message i = 0 for digit in self.number: diff --git a/src/phonebook/views.py b/src/phonebook/views.py index 9f5f0f18..d1083985 100644 --- a/src/phonebook/views.py +++ b/src/phonebook/views.py @@ -82,16 +82,6 @@ class DectRegistrationCreateView(LoginRequiredMixin, CampViewMixin, CreateView): dect.camp = self.camp dect.user = self.request.user - # this check needs to be in this form, but not in model.save(), because then we cant save service numbers from the admin - if len(dect.number) < 4: - form.add_error( - "number", - ValidationError( - "Numbers with fewer than 4 digits are reserved for special use" - ), - ) - return super().form_invalid(form) - try: dect.clean_number() except ValidationError as E: @@ -104,6 +94,16 @@ class DectRegistrationCreateView(LoginRequiredMixin, CampViewMixin, CreateView): form.add_error("letters", E) return super().form_invalid(form) + # this check needs to be in this form, but not in model.save(), because then we cant save service numbers from the admin + if len(dect.number) < 4: + form.add_error( + "number", + ValidationError( + "Numbers with fewer than 4 digits are reserved for special use" + ), + ) + return super().form_invalid(form) + # generate a 10 digit activation code for this dect registration? if not dect.activation_code: dect.activation_code = "".join(