Coverage for benefits / eligibility / forms.py: 92%
60 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-22 19:08 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-22 19:08 +0000
1"""
2The eligibility application: Form definition for the eligibility verification flow.
3"""
5import logging
7from django import forms
8from django.utils.translation import gettext_lazy as _
10from benefits.routes import routes
11from benefits.core import models, widgets
12from benefits.core.mixins import ValidateRecaptchaMixin
14logger = logging.getLogger(__name__)
17class EnrollmentFlowSelectionForm(ValidateRecaptchaMixin, forms.Form):
18 """Form to capture enrollment flow selection."""
20 action_url = routes.ELIGIBILITY_INDEX
21 id = "form-flow-selection"
22 method = "POST"
24 flow = forms.ChoiceField(label="", widget=widgets.FlowRadioSelect)
25 # sets label to empty string so the radio_select template can override the label style
26 submit_value = _("Choose this benefit")
28 def __init__(self, agency: models.TransitAgency, *args, **kwargs):
29 super().__init__(*args, **kwargs)
30 flows = agency.enrollment_flows.filter(supported_enrollment_methods__contains=models.EnrollmentMethods.DIGITAL)
32 # second element is not used since we render the whole label using selection_label_template,
33 # therefore set to None
34 flow_field = self.fields["flow"]
35 flow_field.choices = [(f.id, None) for f in flows]
36 flow_field.widget.selection_label_templates = {f.id: f.selection_label_template for f in flows}
37 flow_field.widget.attrs.update({"data-custom-validity": _("Please choose a transit benefit.")})
38 self.use_custom_validity = True
41class EligibilityVerificationForm(ValidateRecaptchaMixin, forms.Form):
42 """Form to collect eligibility verification details."""
44 action_url = routes.ELIGIBILITY_CONFIRM
45 id = "form-eligibility-verification"
46 method = "POST"
48 submit_value = _("Find my record")
49 submitting_value = _("Checking")
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.
73 Args:
74 title (str): The page (i.e. tab) title for the form's page.
76 headline (str): The <h1> on the form's page.
78 blurb (str): Intro <p> on the form's page.
80 name_label (str): Label for the name form field.
82 name_placeholder (str): Field placeholder for the name form field.
84 name_help_text (str): Extra help text for the name form field.
86 sub_label (str): Label for the sub form field.
88 sub_placeholder (str): Field placeholder for the sub form field.
90 sub_help_text (str): Extra help text for the sub form field.
92 name_max_length (int): The maximum length accepted for the 'name' API field before sending an API request
94 sub_input_mode (str): Input mode can be "numeric", "tel", "search", etc. to override default "text" keyboard on
95 mobile devices
97 sub_max_length (int): The maximum length accepted for the 'sub' API field before sending an API request
99 sub_pattern (str): A regular expression used to validate the 'sub' API field before sending an API request
101 Extra args and kwargs are passed through to the underlying django.forms.Form.
102 """
103 super().__init__(auto_id=True, label_suffix="", *args, **kwargs)
105 self.title = title
106 self.headline = headline
107 self.blurb = blurb
108 self.classes = "eligibility-verification-form"
110 sub_widget = widgets.FormControlTextInput(placeholder=sub_placeholder)
111 if sub_pattern: 111 ↛ 113line 111 didn't jump to line 113 because the condition on line 111 was always true
112 sub_widget.attrs.update({"pattern": sub_pattern})
113 if sub_input_mode: 113 ↛ 115line 113 didn't jump to line 115 because the condition on line 113 was always true
114 sub_widget.attrs.update({"inputmode": sub_input_mode})
115 if sub_max_length: 115 ↛ 117line 115 didn't jump to line 117 because the condition on line 115 was always true
116 sub_widget.attrs.update({"maxlength": sub_max_length})
117 if sub_custom_validity: 117 ↛ 121line 117 didn't jump to line 121 because the condition on line 117 was always true
118 sub_widget.attrs.update({"data-custom-validity": sub_custom_validity})
119 self.use_custom_validity = True
121 self.fields["sub"] = forms.CharField(
122 label=sub_label,
123 widget=sub_widget,
124 help_text=sub_help_text,
125 )
127 name_widget = widgets.FormControlTextInput(placeholder=name_placeholder)
128 if name_max_length: 128 ↛ 130line 128 didn't jump to line 130 because the condition on line 128 was always true
129 name_widget.attrs.update({"maxlength": name_max_length})
130 if name_custom_validity: 130 ↛ 134line 130 didn't jump to line 134 because the condition on line 130 was always true
131 name_widget.attrs.update({"data-custom-validity": name_custom_validity})
132 self.use_custom_validity = True
134 self.fields["name"] = forms.CharField(label=name_label, widget=name_widget, help_text=name_help_text)
137class CSTAgencyCard(EligibilityVerificationForm):
138 """EligibilityVerification form for the CST Agency Card."""
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,
163 )
166class MSTCourtesyCard(EligibilityVerificationForm):
167 """EligibilityVerification form for the MST Courtesy Card."""
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 )
195class SBMTDMobilityPass(EligibilityVerificationForm):
196 """EligibilityVerification form for the SBMTD Reduced Fare Mobility ID."""
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 )