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

1""" 

2The eligibility application: Form definition for the eligibility verification flow. 

3""" 

4 

5import logging 

6 

7from django import forms 

8from django.utils.translation import gettext_lazy as _ 

9 

10from benefits.routes import routes 

11from benefits.core import models, widgets 

12from benefits.core.mixins import ValidateRecaptchaMixin 

13 

14logger = logging.getLogger(__name__) 

15 

16 

17class EnrollmentFlowSelectionForm(ValidateRecaptchaMixin, forms.Form): 

18 """Form to capture enrollment flow selection.""" 

19 

20 action_url = routes.ELIGIBILITY_INDEX 

21 id = "form-flow-selection" 

22 method = "POST" 

23 

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") 

27 

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) 

31 

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 

39 

40 

41class EligibilityVerificationForm(ValidateRecaptchaMixin, forms.Form): 

42 """Form to collect eligibility verification details.""" 

43 

44 action_url = routes.ELIGIBILITY_CONFIRM 

45 id = "form-eligibility-verification" 

46 method = "POST" 

47 

48 submit_value = _("Find my record") 

49 submitting_value = _("Checking") 

50 

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 """ 

103 super().__init__(auto_id=True, label_suffix="", *args, **kwargs) 

104 

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: 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 

120 

121 self.fields["sub"] = forms.CharField( 

122 label=sub_label, 

123 widget=sub_widget, 

124 help_text=sub_help_text, 

125 ) 

126 

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 

133 

134 self.fields["name"] = forms.CharField(label=name_label, widget=name_widget, help_text=name_help_text) 

135 

136 

137class CSTAgencyCard(EligibilityVerificationForm): 

138 """EligibilityVerification form for the CST Agency Card.""" 

139 

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 ) 

164 

165 

166class MSTCourtesyCard(EligibilityVerificationForm): 

167 """EligibilityVerification form for the MST Courtesy Card.""" 

168 

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 ) 

193 

194 

195class SBMTDMobilityPass(EligibilityVerificationForm): 

196 """EligibilityVerification form for the SBMTD Reduced Fare Mobility ID.""" 

197 

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 )