Coverage for benefits/eligibility/forms.py: 95%
66 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-19 00:56 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-19 00:56 +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, recaptcha, widgets
13logger = logging.getLogger(__name__)
16class EnrollmentFlowSelectionForm(forms.Form):
17 """Form to capture enrollment flow selection."""
19 action_url = routes.ELIGIBILITY_INDEX
20 id = "form-flow-selection"
21 method = "POST"
23 flow = forms.ChoiceField(label="", widget=widgets.FlowRadioSelect)
24 # sets label to empty string so the radio_select template can override the label style
25 submit_value = _("Choose this benefit")
27 def __init__(self, agency: models.TransitAgency, *args, **kwargs):
28 super().__init__(*args, **kwargs)
29 flows = agency.enrollment_flows.filter(supported_enrollment_methods__contains=models.EnrollmentMethods.DIGITAL)
31 self.classes = "col-lg-8"
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
40 def clean(self):
41 if not recaptcha.verify(self.data): 41 ↛ 42line 41 didn't jump to line 42 because the condition on line 41 was never true
42 raise forms.ValidationError("reCAPTCHA failed")
45class EligibilityVerificationForm(forms.Form):
46 """Form to collect eligibility verification details."""
48 action_url = routes.ELIGIBILITY_CONFIRM
49 id = "form-eligibility-verification"
50 method = "POST"
52 submit_value = _("Find my record")
53 submitting_value = _("Checking")
55 def __init__(
56 self,
57 title,
58 headline,
59 blurb,
60 name_label,
61 name_placeholder,
62 name_help_text,
63 sub_label,
64 sub_placeholder,
65 sub_help_text,
66 name_max_length=None,
67 sub_input_mode=None,
68 sub_max_length=None,
69 sub_pattern=None,
70 sub_custom_validity=None,
71 name_custom_validity=None,
72 *args,
73 **kwargs,
74 ):
75 """Initialize a new EligibilityVerification form.
77 Args:
78 title (str): The page (i.e. tab) title for the form's page.
80 headline (str): The <h1> on the form's page.
82 blurb (str): Intro <p> on the form's page.
84 name_label (str): Label for the name form field.
86 name_placeholder (str): Field placeholder for the name form field.
88 name_help_text (str): Extra help text for the name form field.
90 sub_label (str): Label for the sub form field.
92 sub_placeholder (str): Field placeholder for the sub form field.
94 sub_help_text (str): Extra help text for the sub form field.
96 name_max_length (int): The maximum length accepted for the 'name' API field before sending an API request
98 sub_input_mode (str): Input mode can be "numeric", "tel", "search", etc. to override default "text" keyboard on
99 mobile devices
101 sub_max_length (int): The maximum length accepted for the 'sub' API field before sending an API request
103 sub_pattern (str): A regular expression used to validate the 'sub' API field before sending an API request
105 Extra args and kwargs are passed through to the underlying django.forms.Form.
106 """
107 super().__init__(auto_id=True, label_suffix="", *args, **kwargs)
109 self.title = title
110 self.headline = headline
111 self.blurb = blurb
113 self.classes = "col-lg-6"
114 sub_widget = widgets.FormControlTextInput(placeholder=sub_placeholder)
115 if sub_pattern:
116 sub_widget.attrs.update({"pattern": sub_pattern})
117 if sub_input_mode:
118 sub_widget.attrs.update({"inputmode": sub_input_mode})
119 if sub_max_length:
120 sub_widget.attrs.update({"maxlength": sub_max_length})
121 if sub_custom_validity:
122 sub_widget.attrs.update({"data-custom-validity": sub_custom_validity})
123 self.use_custom_validity = True
125 self.fields["sub"] = forms.CharField(
126 label=sub_label,
127 widget=sub_widget,
128 help_text=sub_help_text,
129 )
131 name_widget = widgets.FormControlTextInput(placeholder=name_placeholder)
132 if name_max_length:
133 name_widget.attrs.update({"maxlength": name_max_length})
134 if name_custom_validity:
135 name_widget.attrs.update({"data-custom-validity": name_custom_validity})
136 self.use_custom_validity = True
138 self.fields["name"] = forms.CharField(label=name_label, widget=name_widget, help_text=name_help_text)
140 def clean(self):
141 if not recaptcha.verify(self.data): 141 ↛ 142line 141 didn't jump to line 142 because the condition on line 141 was never true
142 raise forms.ValidationError("reCAPTCHA failed")
145class CSTAgencyCard(EligibilityVerificationForm):
146 """EligibilityVerification form for the CST Agency Card."""
148 def __init__(self, *args, **kwargs):
149 super().__init__(
150 title=_("Agency card information"),
151 headline=_("Let’s find the record of your transit benefit."),
152 blurb=_(
153 "We use the information on your CST Agency Card to find the record of your transit benefit in our system."
154 ),
155 name_label=_("Last Name"),
156 name_placeholder="Hernandez-Demarcos",
157 name_help_text=_(
158 "Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
159 ),
160 sub_label=_("Agency Card number"),
161 sub_help_text=_("This is a 5-digit number on the front and back of your card."),
162 sub_placeholder="12345",
163 name_max_length=255,
164 sub_input_mode="numeric",
165 sub_max_length=5,
166 sub_pattern=r"\d{5}",
167 sub_custom_validity=_("Please enter a 5-digit number."),
168 name_custom_validity=_("Please enter your last name."),
169 *args,
170 **kwargs,
171 )
174class MSTCourtesyCard(EligibilityVerificationForm):
175 """EligibilityVerification form for the MST Courtesy Card."""
177 def __init__(self, *args, **kwargs):
178 super().__init__(
179 title=_("Agency card information"),
180 headline=_("Let’s find the record of your transit benefit."),
181 blurb=_(
182 "We use the information on your MST Courtesy Card to find the record of your transit benefit in our system."
183 ),
184 name_label=_("Last Name"),
185 name_placeholder="Garcia",
186 name_help_text=_(
187 "Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
188 ),
189 sub_label=_("Courtesy Card number"),
190 sub_help_text=_("This is a 5-digit number on the front and back of your card."),
191 sub_placeholder="12345",
192 name_max_length=255,
193 sub_input_mode="numeric",
194 sub_max_length=5,
195 sub_pattern=r"\d{5}",
196 sub_custom_validity=_("Please enter a 5-digit number."),
197 name_custom_validity=_("Please enter your last name."),
198 *args,
199 **kwargs,
200 )
203class SBMTDMobilityPass(EligibilityVerificationForm):
204 """EligibilityVerification form for the SBMTD Reduced Fare Mobility ID."""
206 def __init__(self, *args, **kwargs):
207 super().__init__(
208 title=_("Agency card information"),
209 headline=_("Let’s find the record of your transit benefit."),
210 blurb=_(
211 "We use the information on your SBMTD Reduced Fare Mobility ID card to find the record of your transit "
212 + "benefit in our system."
213 ),
214 name_label=_("Last Name"),
215 name_placeholder="Garcia",
216 name_help_text=_(
217 "Please enter your last name the same way it is printed on your card, including capital letters and hyphens."
218 ),
219 sub_label=_("Reduced Fare Mobility ID card number"),
220 sub_help_text=_("This is a 4-digit number on the back of your card."),
221 sub_placeholder="1234",
222 name_max_length=255,
223 sub_input_mode="numeric",
224 sub_max_length=4,
225 sub_pattern=r"\d{4}",
226 sub_custom_validity=_("Please enter a 4-digit number."),
227 name_custom_validity=_("Please enter your last name."),
228 *args,
229 **kwargs,
230 )