mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-03 01:33:32 +02:00
Merge pull request #1613 from cisagov/dk/903-delete-other-contacts
Issue 903: Delete other contacts (DK sandbox)
This commit is contained in:
commit
66cf92e0dd
9 changed files with 503 additions and 151 deletions
|
@ -177,7 +177,7 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
|
||||
# no matching database object, create it
|
||||
# make sure not to create a database object if cleaned has 'delete' attribute
|
||||
elif db_obj is None and cleaned and not cleaned.get("delete", False):
|
||||
elif db_obj is None and cleaned and not cleaned.get("DELETE", False):
|
||||
kwargs = pre_create(db_obj, cleaned)
|
||||
getattr(obj, join).create(**kwargs)
|
||||
|
||||
|
@ -609,9 +609,12 @@ class OtherContactsYesNoForm(RegistrarForm):
|
|||
|
||||
self.fields["has_other_contacts"] = forms.TypedChoiceField(
|
||||
coerce=lambda x: x.lower() == "true" if x is not None else None, # coerce strings to bool, excepting None
|
||||
choices=((True, "Yes, I can name other employees."), (False, "No (We’ll ask you to explain why).")),
|
||||
choices=((True, "Yes, I can name other employees."), (False, "No. (We’ll ask you to explain why.)")),
|
||||
initial=initial_value,
|
||||
widget=forms.RadioSelect,
|
||||
error_messages={
|
||||
"required": "This question is required.",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
@ -638,7 +641,10 @@ class OtherContactsForm(RegistrarForm):
|
|||
)
|
||||
email = forms.EmailField(
|
||||
label="Email",
|
||||
error_messages={"invalid": ("Enter an email address in the required format, like name@example.com.")},
|
||||
error_messages={
|
||||
"required": ("Enter an email address in the required format, like name@example.com."),
|
||||
"invalid": ("Enter an email address in the required format, like name@example.com."),
|
||||
},
|
||||
)
|
||||
phone = PhoneNumberField(
|
||||
label="Phone",
|
||||
|
@ -649,8 +655,17 @@ class OtherContactsForm(RegistrarForm):
|
|||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Override the __init__ method for RegistrarForm.
|
||||
Set form_data_marked_for_deletion to false.
|
||||
Empty_permitted set to False, as this is overridden in certain circumstances by
|
||||
Django's BaseFormSet, and results in empty forms being allowed and field level
|
||||
errors not appropriately raised. This works with code in the view which appropriately
|
||||
displays required attributes on fields.
|
||||
"""
|
||||
self.form_data_marked_for_deletion = False
|
||||
super().__init__(*args, **kwargs)
|
||||
self.empty_permitted = False
|
||||
|
||||
def mark_form_for_deletion(self):
|
||||
self.form_data_marked_for_deletion = True
|
||||
|
@ -659,12 +674,11 @@ class OtherContactsForm(RegistrarForm):
|
|||
"""
|
||||
This method overrides the default behavior for forms.
|
||||
This cleans the form after field validation has already taken place.
|
||||
In this override, allow for a form which is empty to be considered
|
||||
valid even though certain required fields have not passed field
|
||||
validation
|
||||
In this override, allow for a form which is deleted by user or marked for
|
||||
deletion by formset to be considered valid even though certain required fields have
|
||||
not passed field validation
|
||||
"""
|
||||
|
||||
if self.form_data_marked_for_deletion:
|
||||
if self.form_data_marked_for_deletion or self.cleaned_data.get("DELETE"):
|
||||
# clear any errors raised by the form fields
|
||||
# (before this clean() method is run, each field
|
||||
# performs its own clean, which could result in
|
||||
|
@ -678,12 +692,26 @@ class OtherContactsForm(RegistrarForm):
|
|||
# return empty object with only 'delete' attribute defined.
|
||||
# this will prevent _to_database from creating an empty
|
||||
# database object
|
||||
return {"delete": True}
|
||||
return {"DELETE": True}
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
|
||||
class BaseOtherContactsFormSet(RegistrarFormSet):
|
||||
"""
|
||||
FormSet for Other Contacts
|
||||
|
||||
There are two conditions by which a form in the formset can be marked for deletion.
|
||||
One is if the user clicks 'DELETE' button, and this is submitted in the form. The
|
||||
other is if the YesNo form, which is submitted with this formset, is set to No; in
|
||||
this case, all forms in formset are marked for deletion. Both of these conditions
|
||||
must co-exist.
|
||||
Also, other_contacts have db relationships to multiple db objects. When attempting
|
||||
to delete an other_contact from an application, those db relationships must be
|
||||
tested and handled; this is configured with REVERSE_JOINS, which is an array of
|
||||
strings representing the relationships between contact model and other models.
|
||||
"""
|
||||
|
||||
JOIN = "other_contacts"
|
||||
REVERSE_JOINS = [
|
||||
"user",
|
||||
|
@ -695,7 +723,13 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
"contact_applications_information",
|
||||
]
|
||||
|
||||
def get_deletion_widget(self):
|
||||
return forms.HiddenInput(attrs={"class": "deletion"})
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Override __init__ for RegistrarFormSet.
|
||||
"""
|
||||
self.formset_data_marked_for_deletion = False
|
||||
self.application = kwargs.pop("application", None)
|
||||
super(RegistrarFormSet, self).__init__(*args, **kwargs)
|
||||
|
@ -706,8 +740,17 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
self.forms[index].use_required_attribute = True
|
||||
|
||||
def should_delete(self, cleaned):
|
||||
empty = (isinstance(v, str) and (v.strip() == "" or v is None) for v in cleaned.values())
|
||||
return all(empty) or self.formset_data_marked_for_deletion
|
||||
"""
|
||||
Implements should_delete method from BaseFormSet.
|
||||
"""
|
||||
return self.formset_data_marked_for_deletion or cleaned.get("DELETE", False)
|
||||
|
||||
def pre_create(self, db_obj, cleaned):
|
||||
"""Code to run before an item in the formset is created in the database."""
|
||||
# remove DELETE from cleaned
|
||||
if "DELETE" in cleaned:
|
||||
cleaned.pop("DELETE")
|
||||
return cleaned
|
||||
|
||||
def to_database(self, obj: DomainApplication):
|
||||
self._to_database(obj, self.JOIN, self.REVERSE_JOINS, self.should_delete, self.pre_update, self.pre_create)
|
||||
|
@ -736,9 +779,10 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
|
||||
OtherContactsFormSet = forms.formset_factory(
|
||||
OtherContactsForm,
|
||||
extra=1,
|
||||
extra=0,
|
||||
absolute_max=1500, # django default; use `max_num` to limit entries
|
||||
min_num=1,
|
||||
can_delete=True,
|
||||
validate_min=True,
|
||||
formset=BaseOtherContactsFormSet,
|
||||
)
|
||||
|
@ -748,11 +792,7 @@ class NoOtherContactsForm(RegistrarForm):
|
|||
no_other_contacts_rationale = forms.CharField(
|
||||
required=True,
|
||||
# label has to end in a space to get the label_suffix to show
|
||||
label=(
|
||||
"You don’t need to provide names of other employees now, but it may "
|
||||
"slow down our assessment of your eligibility. Describe why there are "
|
||||
"no other employees who can help verify your request."
|
||||
),
|
||||
label=("No other employees rationale"),
|
||||
widget=forms.Textarea(),
|
||||
validators=[
|
||||
MaxLengthValidator(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue