Skip to content

Commit 35dae6f

Browse files
authored
Refactor: simplify eligibility verification forms (#3392)
2 parents 9da54ad + 360421e commit 35dae6f

4 files changed

Lines changed: 261 additions & 243 deletions

File tree

benefits/eligibility/forms.py

Lines changed: 88 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66

77
from django import forms
8+
from django.core.validators import RegexValidator
89
from django.utils.translation import gettext_lazy as _
910

1011
from benefits.routes import routes
@@ -39,184 +40,119 @@ def __init__(self, agency: models.TransitAgency, *args, **kwargs):
3940

4041

4142
class EligibilityVerificationForm(ValidateRecaptchaMixin, forms.Form):
42-
"""Form to collect eligibility verification details."""
43+
"""Base form to collect eligibility verification details."""
4344

4445
action_url = routes.ELIGIBILITY_CONFIRM
4546
id = "form-eligibility-verification"
4647
method = "POST"
4748

4849
submit_value = _("Find my record")
4950
submitting_value = _("Checking")
51+
classes = "eligibility-verification-form"
52+
53+
# Default configuration attributes (override in subclasses)
54+
title = _("Agency card information")
55+
headline = _("Let’s find the record of your transit benefit.")
56+
blurb = None
57+
58+
name_label = _("Last Name")
59+
name_placeholder = "Garcia"
60+
name_help_text = _(
61+
"Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
62+
)
63+
name_max_length = 255
64+
name_custom_validity = _("Please enter your last name.")
65+
66+
sub_label = None
67+
sub_placeholder = None
68+
sub_help_text = None
69+
sub_input_mode = None
70+
sub_max_length = None
71+
sub_pattern = None
72+
sub_custom_validity = None
5073

51-
def __init__(
52-
self,
53-
title,
54-
headline,
55-
blurb,
56-
name_label,
57-
name_placeholder,
58-
name_help_text,
59-
sub_label,
60-
sub_placeholder,
61-
sub_help_text,
62-
name_max_length=None,
63-
sub_input_mode=None,
64-
sub_max_length=None,
65-
sub_pattern=None,
66-
sub_custom_validity=None,
67-
name_custom_validity=None,
68-
*args,
69-
**kwargs,
70-
):
71-
"""Initialize a new EligibilityVerification form.
72-
73-
Args:
74-
title (str): The page (i.e. tab) title for the form's page.
75-
76-
headline (str): The <h1> on the form's page.
77-
78-
blurb (str): Intro <p> on the form's page.
79-
80-
name_label (str): Label for the name form field.
81-
82-
name_placeholder (str): Field placeholder for the name form field.
83-
84-
name_help_text (str): Extra help text for the name form field.
85-
86-
sub_label (str): Label for the sub form field.
87-
88-
sub_placeholder (str): Field placeholder for the sub form field.
89-
90-
sub_help_text (str): Extra help text for the sub form field.
91-
92-
name_max_length (int): The maximum length accepted for the 'name' API field before sending an API request
93-
94-
sub_input_mode (str): Input mode can be "numeric", "tel", "search", etc. to override default "text" keyboard on
95-
mobile devices
96-
97-
sub_max_length (int): The maximum length accepted for the 'sub' API field before sending an API request
98-
99-
sub_pattern (str): A regular expression used to validate the 'sub' API field before sending an API request
100-
101-
Extra args and kwargs are passed through to the underlying django.forms.Form.
102-
"""
74+
def __init__(self, *args, **kwargs):
75+
"""Initialize the form using class attributes for configuration."""
10376
super().__init__(auto_id=True, label_suffix="", *args, **kwargs)
10477

105-
self.title = title
106-
self.headline = headline
107-
self.blurb = blurb
108-
self.classes = "eligibility-verification-form"
109-
110-
sub_widget = widgets.FormControlTextInput(placeholder=sub_placeholder)
111-
if sub_pattern:
112-
sub_widget.attrs.update({"pattern": sub_pattern})
113-
if sub_input_mode:
114-
sub_widget.attrs.update({"inputmode": sub_input_mode})
115-
if sub_max_length:
116-
sub_widget.attrs.update({"maxlength": sub_max_length})
117-
if sub_custom_validity:
118-
sub_widget.attrs.update({"data-custom-validity": sub_custom_validity})
78+
# Configure the 'sub' field (ID/Card Number)
79+
sub_widget = widgets.FormControlTextInput(placeholder=self.sub_placeholder)
80+
81+
if self.sub_pattern:
82+
sub_widget.attrs.update({"pattern": self.sub_pattern})
83+
if self.sub_input_mode:
84+
sub_widget.attrs.update({"inputmode": self.sub_input_mode})
85+
if self.sub_max_length:
86+
sub_widget.attrs.update({"maxlength": self.sub_max_length})
87+
if self.sub_custom_validity:
88+
sub_widget.attrs.update({"data-custom-validity": self.sub_custom_validity})
11989
self.use_custom_validity = True
12090

91+
sub_validators = []
92+
if self.sub_pattern and self.sub_custom_validity:
93+
sub_validators.append(RegexValidator(regex=self.sub_pattern, message=self.sub_custom_validity))
94+
12195
self.fields["sub"] = forms.CharField(
122-
label=sub_label,
96+
label=self.sub_label,
12397
widget=sub_widget,
124-
help_text=sub_help_text,
98+
help_text=self.sub_help_text,
99+
max_length=self.sub_max_length,
100+
validators=sub_validators,
125101
)
126102

127-
name_widget = widgets.FormControlTextInput(placeholder=name_placeholder)
128-
if name_max_length:
129-
name_widget.attrs.update({"maxlength": name_max_length})
130-
if name_custom_validity:
131-
name_widget.attrs.update({"data-custom-validity": name_custom_validity})
132-
self.use_custom_validity = True
133-
134-
self.fields["name"] = forms.CharField(label=name_label, widget=name_widget, help_text=name_help_text)
135-
103+
# Configure the 'name' field
104+
name_widget = widgets.FormControlTextInput(placeholder=self.name_placeholder)
136105

137-
class CSTAgencyCard(EligibilityVerificationForm):
138-
"""EligibilityVerification form for the CST Agency Card."""
106+
if self.name_max_length:
107+
name_widget.attrs.update({"maxlength": self.name_max_length})
108+
if self.name_custom_validity:
109+
name_widget.attrs.update({"data-custom-validity": self.name_custom_validity})
110+
self.use_custom_validity = True
139111

140-
def __init__(self, *args, **kwargs):
141-
super().__init__(
142-
title=_("Agency card information"),
143-
headline=_("Let’s find the record of your transit benefit."),
144-
blurb=_(
145-
"We use the information on your CST Agency Card to find the record of your transit benefit in our system."
146-
),
147-
name_label=_("Last Name"),
148-
name_placeholder="Hernandez-Demarcos",
149-
name_help_text=_(
150-
"Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
151-
),
152-
sub_label=_("Agency Card number"),
153-
sub_help_text=_("This is a 5-digit number on the front and back of your card."),
154-
sub_placeholder="12345",
155-
name_max_length=255,
156-
sub_input_mode="numeric",
157-
sub_max_length=5,
158-
sub_pattern=r"\d{5}",
159-
sub_custom_validity=_("Please enter a 5-digit number."),
160-
name_custom_validity=_("Please enter your last name."),
161-
*args,
162-
**kwargs,
112+
self.fields["name"] = forms.CharField(
113+
label=self.name_label,
114+
widget=name_widget,
115+
help_text=self.name_help_text,
116+
max_length=self.name_max_length,
163117
)
164118

165119

166120
class MSTCourtesyCard(EligibilityVerificationForm):
167121
"""EligibilityVerification form for the MST Courtesy Card."""
168122

169-
def __init__(self, *args, **kwargs):
170-
super().__init__(
171-
title=_("Agency card information"),
172-
headline=_("Let’s find the record of your transit benefit."),
173-
blurb=_(
174-
"We use the information on your MST Courtesy Card to find the record of your transit benefit in our system."
175-
),
176-
name_label=_("Last Name"),
177-
name_placeholder="Garcia",
178-
name_help_text=_(
179-
"Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
180-
),
181-
sub_label=_("Courtesy Card number"),
182-
sub_help_text=_("This is a 5-digit number on the front and back of your card."),
183-
sub_placeholder="12345",
184-
name_max_length=255,
185-
sub_input_mode="numeric",
186-
sub_max_length=5,
187-
sub_pattern=r"\d{5}",
188-
sub_custom_validity=_("Please enter a 5-digit number."),
189-
name_custom_validity=_("Please enter your last name."),
190-
*args,
191-
**kwargs,
192-
)
123+
blurb = _("We use the information on your MST Courtesy Card to find the record of your transit benefit in our system.")
124+
125+
sub_label = _("Courtesy Card number")
126+
sub_placeholder = "12345"
127+
sub_help_text = _("This is a 5-digit number on the front and back of your card.")
128+
sub_input_mode = "numeric"
129+
sub_max_length = 5
130+
sub_pattern = r"\d{5}"
131+
sub_custom_validity = _("Please enter a 5-digit number.")
132+
133+
134+
class CSTAgencyCard(MSTCourtesyCard):
135+
"""
136+
EligibilityVerification form for the CST Agency Card.
137+
Inherits validation logic from MSTCourtesyCard but overrides specific text.
138+
"""
139+
140+
blurb = _("We use the information on your CST Agency Card to find the record of your transit benefit in our system.")
141+
142+
sub_label = _("Agency Card number")
193143

194144

195145
class SBMTDMobilityPass(EligibilityVerificationForm):
196146
"""EligibilityVerification form for the SBMTD Reduced Fare Mobility ID."""
197147

198-
def __init__(self, *args, **kwargs):
199-
super().__init__(
200-
title=_("Agency card information"),
201-
headline=_("Let’s find the record of your transit benefit."),
202-
blurb=_(
203-
"We use the information on your SBMTD Reduced Fare Mobility ID card to find the record of your transit "
204-
+ "benefit in our system."
205-
),
206-
name_label=_("Last Name"),
207-
name_placeholder="Garcia",
208-
name_help_text=_(
209-
"Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
210-
),
211-
sub_label=_("Reduced Fare Mobility ID card number"),
212-
sub_help_text=_("This is a 4- or 5-digit number on the back of your card."),
213-
sub_placeholder="12345",
214-
name_max_length=255,
215-
sub_input_mode="numeric",
216-
sub_max_length=5,
217-
sub_pattern=r"\d{4,5}",
218-
sub_custom_validity=_("Please enter a 4- or 5-digit number."),
219-
name_custom_validity=_("Please enter your last name."),
220-
*args,
221-
**kwargs,
222-
)
148+
blurb = _(
149+
"We use the information on your SBMTD Reduced Fare Mobility ID card to find the record of your transit benefit in our system." # noqa: E501
150+
)
151+
152+
sub_label = _("Reduced Fare Mobility ID card number")
153+
sub_placeholder = "12345"
154+
sub_help_text = _("This is a 4- or 5-digit number on the back of your card.")
155+
sub_input_mode = "numeric"
156+
sub_max_length = 5
157+
sub_pattern = r"\d{4,5}"
158+
sub_custom_validity = _("Please enter a 4- or 5-digit number.")

benefits/locale/en/LC_MESSAGES/django.po

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
msgid ""
77
msgstr ""
88
"Report-Msgid-Bugs-To: https://github.com/cal-itp/benefits/issues \n"
9-
"POT-Creation-Date: 2025-11-18 09:00-0800\n"
9+
"POT-Creation-Date: 2025-12-17 13:43-0800\n"
1010
"Language: English\n"
1111
"MIME-Version: 1.0\n"
1212
"Content-Type: text/plain; charset=UTF-8\n"
@@ -543,11 +543,6 @@ msgstr ""
543543
msgid "Let’s find the record of your transit benefit."
544544
msgstr ""
545545

546-
msgid ""
547-
"We use the information on your CST Agency Card to find the record of your "
548-
"transit benefit in our system."
549-
msgstr ""
550-
551546
msgid "Last Name"
552547
msgstr ""
553548

@@ -556,24 +551,29 @@ msgid ""
556551
"including capital letters and hyphens."
557552
msgstr ""
558553

559-
msgid "Agency Card number"
554+
msgid "Please enter your last name."
560555
msgstr ""
561556

562-
msgid "This is a 5-digit number on the front and back of your card."
557+
msgid ""
558+
"We use the information on your MST Courtesy Card to find the record of your "
559+
"transit benefit in our system."
563560
msgstr ""
564561

565-
msgid "Please enter a 5-digit number."
562+
msgid "Courtesy Card number"
566563
msgstr ""
567564

568-
msgid "Please enter your last name."
565+
msgid "This is a 5-digit number on the front and back of your card."
566+
msgstr ""
567+
568+
msgid "Please enter a 5-digit number."
569569
msgstr ""
570570

571571
msgid ""
572-
"We use the information on your MST Courtesy Card to find the record of your "
572+
"We use the information on your CST Agency Card to find the record of your "
573573
"transit benefit in our system."
574574
msgstr ""
575575

576-
msgid "Courtesy Card number"
576+
msgid "Agency Card number"
577577
msgstr ""
578578

579579
msgid ""

benefits/locale/es/LC_MESSAGES/django.po

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
msgid ""
77
msgstr ""
88
"Report-Msgid-Bugs-To: https://github.com/cal-itp/benefits/issues \n"
9-
"POT-Creation-Date: 2025-11-18 09:00-0800\n"
9+
"POT-Creation-Date: 2025-12-17 13:43-0800\n"
1010
"Language: Español\n"
1111
"MIME-Version: 1.0\n"
1212
"Content-Type: text/plain; charset=UTF-8\n"
@@ -717,13 +717,6 @@ msgstr "Información de la tarjeta de agencia"
717717
msgid "Let’s find the record of your transit benefit."
718718
msgstr "Veamos si podemos confirmar su elegibilidad."
719719

720-
msgid ""
721-
"We use the information on your CST Agency Card to find the record of your "
722-
"transit benefit in our system."
723-
msgstr ""
724-
"Utilizamos la información de su Tarjeta de agencia CST para encontrar el "
725-
"registro de su beneficio de tránsito en nuestro sistema."
726-
727720
msgid "Last Name"
728721
msgstr "Apellido"
729722

@@ -734,15 +727,6 @@ msgstr ""
734727
"Ingrese su apellido de la misma manera que está impreso en su tarjeta, "
735728
"incluyendo mayúsculas y guiones."
736729

737-
msgid "Agency Card number"
738-
msgstr "Número de tarjeta de agencia de CST"
739-
740-
msgid "This is a 5-digit number on the front and back of your card."
741-
msgstr "Este es un número de 5 dígitos en el anverso y reverso de su tarjeta."
742-
743-
msgid "Please enter a 5-digit number."
744-
msgstr "Ingrese un número de 5 dígitos."
745-
746730
msgid "Please enter your last name."
747731
msgstr "Ingrese su apellido."
748732

@@ -756,6 +740,22 @@ msgstr ""
756740
msgid "Courtesy Card number"
757741
msgstr "Número de tarjeta de cortesía de MST"
758742

743+
msgid "This is a 5-digit number on the front and back of your card."
744+
msgstr "Este es un número de 5 dígitos en el anverso y reverso de su tarjeta."
745+
746+
msgid "Please enter a 5-digit number."
747+
msgstr "Ingrese un número de 5 dígitos."
748+
749+
msgid ""
750+
"We use the information on your CST Agency Card to find the record of your "
751+
"transit benefit in our system."
752+
msgstr ""
753+
"Utilizamos la información de su Tarjeta de agencia CST para encontrar el "
754+
"registro de su beneficio de tránsito en nuestro sistema."
755+
756+
msgid "Agency Card number"
757+
msgstr "Número de tarjeta de agencia de CST"
758+
759759
msgid ""
760760
"We use the information on your SBMTD Reduced Fare Mobility ID card to find "
761761
"the record of your transit benefit in our system."

0 commit comments

Comments
 (0)