incremental progress

This commit is contained in:
David Kennedy 2024-01-03 06:42:44 -05:00
parent 55f9792b32
commit ce16ecbfb1
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
2 changed files with 213 additions and 31 deletions

View file

@ -551,6 +551,7 @@ class YourContactForm(RegistrarForm):
class OtherContactsYesNoForm(RegistrarForm): class OtherContactsYesNoForm(RegistrarForm):
has_other_contacts = forms.TypedChoiceField( has_other_contacts = forms.TypedChoiceField(
coerce=lambda x: x.lower() == 'true',
choices=( choices=(
(True, "Yes, I can name other employees."), (True, "Yes, I can name other employees."),
(False, "No (We'll ask you to explain why).") (False, "No (We'll ask you to explain why).")
@ -594,6 +595,15 @@ class OtherContactsForm(RegistrarForm):
error_messages={"required": "Enter a phone number for this contact."}, error_messages={"required": "Enter a phone number for this contact."},
) )
def __init__(self, *args, **kwargs):
self.form_data_deleted = False
super().__init__(*args, **kwargs)
def remove_form_data(self):
logger.info("removing form data from other contact")
self.data = {}
self.form_data_deleted = True
def clean(self): def clean(self):
""" """
This method overrides the default behavior for forms. This method overrides the default behavior for forms.
@ -603,29 +613,35 @@ class OtherContactsForm(RegistrarForm):
validation validation
""" """
# Set form_is_empty to True initially if self.form_data_deleted:
form_is_empty = True # Set form_is_empty to True initially
for name, field in self.fields.items(): form_is_empty = True
# get the value of the field from the widget for name, field in self.fields.items():
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) # get the value of the field from the widget
# if any field in the submitted form is not empty, set form_is_empty to False value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
if value is not None and value != "": # if any field in the submitted form is not empty, set form_is_empty to False
form_is_empty = False if value is not None and value != "":
form_is_empty = False
if form_is_empty: if form_is_empty:
# clear any errors raised by the form fields # clear any errors raised by the form fields
# (before this clean() method is run, each field # (before this clean() method is run, each field
# performs its own clean, which could result in # performs its own clean, which could result in
# errors that we wish to ignore at this point) # errors that we wish to ignore at this point)
# #
# NOTE: we cannot just clear() the errors list. # NOTE: we cannot just clear() the errors list.
# That causes problems. # That causes problems.
for field in self.fields: for field in self.fields:
if field in self.errors: if field in self.errors:
del self.errors[field] del self.errors[field]
return self.cleaned_data return self.cleaned_data
def is_valid(self):
val = super().is_valid()
logger.info(f"other contacts form is valid = {val}")
return val
class BaseOtherContactsFormSet(RegistrarFormSet): class BaseOtherContactsFormSet(RegistrarFormSet):
JOIN = "other_contacts" JOIN = "other_contacts"
@ -635,12 +651,18 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
return all(empty) return all(empty)
def to_database(self, obj: DomainApplication): def to_database(self, obj: DomainApplication):
logger.info("to_database called on BaseOtherContactsFormSet")
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create) self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
@classmethod @classmethod
def from_database(cls, obj): def from_database(cls, obj):
return super().from_database(obj, cls.JOIN, cls.on_fetch) return super().from_database(obj, cls.JOIN, cls.on_fetch)
def remove_form_data(self):
logger.info("removing form data from other contact set")
for form in self.forms:
form.remove_form_data()
OtherContactsFormSet = forms.formset_factory( OtherContactsFormSet = forms.formset_factory(
OtherContactsForm, OtherContactsForm,
@ -667,6 +689,63 @@ class NoOtherContactsForm(RegistrarForm):
], ],
) )
def __init__(self, *args, **kwargs):
self.form_data_marked_for_deletion = False
super().__init__(*args, **kwargs)
def remove_form_data(self):
logger.info("removing form data from no other contacts")
# self.data = {"no_other_contacts_rationale": ""}
self.form_data_marked_for_deletion = True
def clean(self):
"""
This method overrides the default behavior for forms.
This cleans the form after field validation has already taken place.
In this override, remove errors associated with the form if form data
is marked for deletion.
"""
if self.form_data_marked_for_deletion:
# clear any errors raised by the form fields
# (before this clean() method is run, each field
# performs its own clean, which could result in
# errors that we wish to ignore at this point)
#
# NOTE: we cannot just clear() the errors list.
# That causes problems.
for field in self.fields:
if field in self.errors:
del self.errors[field]
return self.cleaned_data
def to_database(self, obj):
"""
This method overrides the behavior of RegistrarForm.
If form data is marked for deletion, set relevant fields
to None before saving.
Do nothing if form is not valid.
"""
logger.info(f"to_database called on {self.__class__.__name__}")
if not self.is_valid():
return
if self.form_data_marked_for_deletion:
for field_name, _ in self.fields.items():
logger.info(f"{field_name}: None")
setattr(obj, field_name, None)
else:
for name, value in self.cleaned_data.items():
logger.info(f"{name}: {value}")
setattr(obj, name, value)
obj.save()
def is_valid(self):
"""This is for debugging only and can be deleted"""
val = super().is_valid()
logger.info(f"no other contacts form is valid = {val}")
return val
class AnythingElseForm(RegistrarForm): class AnythingElseForm(RegistrarForm):
anything_else = forms.CharField( anything_else = forms.CharField(

View file

@ -487,21 +487,124 @@ class OtherContacts(ApplicationWizard):
forms = [forms.OtherContactsYesNoForm, forms.OtherContactsFormSet, forms.NoOtherContactsForm] forms = [forms.OtherContactsYesNoForm, forms.OtherContactsFormSet, forms.NoOtherContactsForm]
def post(self, request, *args, **kwargs) -> HttpResponse: def post(self, request, *args, **kwargs) -> HttpResponse:
parent_form = forms.OtherContactsYesNoForm(request.POST) """This method handles POST requests."""
other_contacts_formset = forms.OtherContactsFormSet(request.POST, request.FILES) # Log the keys and values of request.POST
no_other_contacts_form = forms.NoOtherContactsForm(request.POST) for key, value in request.POST.items():
logger.info("Key: %s, Value: %s", key, value)
# if accessing this class directly, redirect to the first step
if self.__class__ == ApplicationWizard:
return self.goto(self.steps.first)
logger.info("in post") # which button did the user press?
has_other_contacts_selected = parent_form.data.get('other_contacts-has_other_contacts') button: str = request.POST.get("submit_button", "")
logger.info(f"has other contacts = {has_other_contacts_selected}")
if parent_form.is_valid(): forms = self.get_forms(use_post=True)
if has_other_contacts_selected: # forms is now set as follows:
# forms.0 is yes no form
# forms.1 - forms.length-1 are other contacts forms
# forms.length is no other contacts form
yes_no_form = forms[0]
other_contacts_forms = forms[1]
no_other_contacts_form = forms[2]
all_forms_valid = True
# test first for yes_no_form validity
if yes_no_form.is_valid():
logger.info("yes no form is valid")
# test for has_contacts
if yes_no_form.cleaned_data.get('has_other_contacts'):
logger.info("has other contacts") logger.info("has other contacts")
other_contacts_formset.data = {} # remove data from no_other_contacts_form and set
# form to always_valid
no_other_contacts_form.remove_form_data()
# test that the other_contacts_forms and no_other_contacts_forms are valid
if not self.is_valid(forms[1:]):
all_forms_valid = False
else: else:
logger.info("doesn't have other contacts") logger.info("has no other contacts")
no_other_contacts_form.data = {} # remove data from each other_contacts_form
super().post(request, *args, **kwargs) other_contacts_forms.remove_form_data()
# test that the other_contacts_forms and no_other_contacts_forms are valid
if not self.is_valid(forms[1:]):
all_forms_valid = False
else:
all_forms_valid = False
if all_forms_valid:
logger.info("all forms are valid")
# always save progress
self.save(forms)
else:
context = self.get_context_data()
context["forms"] = forms
return render(request, self.template_name, context)
# if user opted to save their progress,
# return them to the page they were already on
if button == "save":
messages.success(request, "Your progress has been saved!")
return self.goto(self.steps.current)
# if user opted to save progress and return,
# return them to the home page
if button == "save_and_return":
return HttpResponseRedirect(reverse("home"))
# otherwise, proceed as normal
return self.goto_next_step()
# def post(self, request, *args, **kwargs) -> HttpResponse:
# parent_form = forms.OtherContactsYesNoForm(request.POST, **kwargs)
# other_contacts_formset = forms.OtherContactsFormSet(request.POST, **kwargs)
# no_other_contacts_form = forms.NoOtherContactsForm(request.POST, **kwargs)
# logger.info("in post")
# has_other_contacts_selected = parent_form.data.get('other_contacts-has_other_contacts')
# logger.info(f"has other contacts = {has_other_contacts_selected}")
# if has_other_contacts_selected:
# logger.info("has other contacts")
# other_contacts_formset.data = {}
# else:
# logger.info("doesn't have other contacts")
# no_other_contacts_form.data = {}
# return super().post(request, *args, **kwargs)
# def is_valid(self, forms: list) -> bool:
# """Returns True if all forms in the wizard are valid."""
# if forms[0].is_valid():
# # test for has_contacts
# if forms[0].cleaned_data.get('has_other_contacts'):
# logger.info("testing validity on other contacts")
# validity_list = []
# # Iterate over the sublist of forms from index 2 to the second-to-last index
# for form in forms[1:-1]:
# # Check if the form is valid and append the result to the validity_list
# logger.info(f"testing validity of form of type {form.__class__.__name__}")
# validity_list.append(form.is_valid())
# # Check if all elements in validity_list are True
# return all(validity_list)
# # return all(form.is_valid() for form in forms[2:-2])
# else:
# logger.info("testing validity on no other contacts")
# return forms[-1].is_valid()
# # if has contacts , return if next length-2 are valid
# # else return last form in list is valid
# else:
# return False
# # are_valid = (form.is_valid() for form in forms)
# # return all(are_valid)
# def save(self, forms: list):
# """
# Unpack the form responses onto the model object properties.
# Saves the application to the database.
# """
# logger.info("in save")
# for form in forms:
# if form is not None and hasattr(form, "to_database"):
# form.to_database(self.application)
class NoOtherContacts(ApplicationWizard): class NoOtherContacts(ApplicationWizard):