make entering a DECT phonenumber optional if letters were entered, and handle lowercase letters better

This commit is contained in:
Thomas Steen Rasmussen 2020-03-10 19:45:23 +01:00
parent e02e912c5d
commit 37a2fb6a93
4 changed files with 62 additions and 18 deletions

View file

@ -51,5 +51,5 @@ class DectUtils:
""" """
result = "" result = ""
for letter in letters: for letter in letters:
result += self.REVERSE_DECT_MATRIX[letter] result += self.REVERSE_DECT_MATRIX[letter.upper()]
return result return result

View file

@ -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,
),
),
]

View file

@ -8,6 +8,7 @@ from utils.models import CampRelatedModel
from .dectutils import DectUtils from .dectutils import DectUtils
logger = logging.getLogger("bornhack.%s" % __name__) logger = logging.getLogger("bornhack.%s" % __name__)
dectutil = DectUtils()
class DectRegistration(CampRelatedModel): class DectRegistration(CampRelatedModel):
@ -29,13 +30,15 @@ class DectRegistration(CampRelatedModel):
) )
number = models.CharField( 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( letters = models.CharField(
max_length=9, max_length=9,
blank=True, 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( description = models.TextField(
@ -55,6 +58,7 @@ class DectRegistration(CampRelatedModel):
""" """
This is just here so we get the validation in the admin as well. 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_number()
self.clean_letters() self.clean_letters()
super().save(*args, **kwargs) 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() 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. 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 # First of all, check that number is numeric
try: try:
int(self.number) int(self.number)
@ -77,7 +91,7 @@ class DectRegistration(CampRelatedModel):
.exclude(pk=self.pk) .exclude(pk=self.pk)
.exists() .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 # check for conflicts with a longer number
if ( if (
@ -88,7 +102,7 @@ class DectRegistration(CampRelatedModel):
.exists() .exists()
): ):
raise ValidationError( 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 # check if a shorter number is blocking
@ -100,7 +114,7 @@ class DectRegistration(CampRelatedModel):
.exists() .exists()
): ):
raise ValidationError( 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 i -= 1
@ -118,14 +132,13 @@ class DectRegistration(CampRelatedModel):
) )
# loop over the digits in the phonenumber # loop over the digits in the phonenumber
dectutil = DectUtils()
combinations = list(dectutil.get_dect_letter_combinations(self.number)) combinations = list(dectutil.get_dect_letter_combinations(self.number))
if not combinations: if not combinations:
raise ValidationError( raise ValidationError(
"Numbers with 0 and 1 in them can not be expressed as letters" "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 # something is fucky, loop over letters to give a better error message
i = 0 i = 0
for digit in self.number: for digit in self.number:

View file

@ -82,16 +82,6 @@ class DectRegistrationCreateView(LoginRequiredMixin, CampViewMixin, CreateView):
dect.camp = self.camp dect.camp = self.camp
dect.user = self.request.user 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: try:
dect.clean_number() dect.clean_number()
except ValidationError as E: except ValidationError as E:
@ -104,6 +94,16 @@ class DectRegistrationCreateView(LoginRequiredMixin, CampViewMixin, CreateView):
form.add_error("letters", E) form.add_error("letters", E)
return super().form_invalid(form) 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? # generate a 10 digit activation code for this dect registration?
if not dect.activation_code: if not dect.activation_code:
dect.activation_code = "".join( dect.activation_code = "".join(