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

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, recaptcha, widgets 

12 

13logger = logging.getLogger(__name__) 

14 

15 

16class EnrollmentFlowSelectionForm(forms.Form): 

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

18 

19 action_url = routes.ELIGIBILITY_INDEX 

20 id = "form-flow-selection" 

21 method = "POST" 

22 

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

26 

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) 

30 

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 

39 

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

43 

44 

45class EligibilityVerificationForm(forms.Form): 

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

47 

48 action_url = routes.ELIGIBILITY_CONFIRM 

49 id = "form-eligibility-verification" 

50 method = "POST" 

51 

52 submit_value = _("Find my record") 

53 submitting_value = _("Checking") 

54 

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. 

76 

77 Args: 

78 title (str): The page (i.e. tab) title for the form's page. 

79 

80 headline (str): The <h1> on the form's page. 

81 

82 blurb (str): Intro <p> on the form's page. 

83 

84 name_label (str): Label for the name form field. 

85 

86 name_placeholder (str): Field placeholder for the name form field. 

87 

88 name_help_text (str): Extra help text for the name form field. 

89 

90 sub_label (str): Label for the sub form field. 

91 

92 sub_placeholder (str): Field placeholder for the sub form field. 

93 

94 sub_help_text (str): Extra help text for the sub form field. 

95 

96 name_max_length (int): The maximum length accepted for the 'name' API field before sending an API request 

97 

98 sub_input_mode (str): Input mode can be "numeric", "tel", "search", etc. to override default "text" keyboard on 

99 mobile devices 

100 

101 sub_max_length (int): The maximum length accepted for the 'sub' API field before sending an API request 

102 

103 sub_pattern (str): A regular expression used to validate the 'sub' API field before sending an API request 

104 

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) 

108 

109 self.title = title 

110 self.headline = headline 

111 self.blurb = blurb 

112 

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 

124 

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

126 label=sub_label, 

127 widget=sub_widget, 

128 help_text=sub_help_text, 

129 ) 

130 

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 

137 

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

139 

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

143 

144 

145class CSTAgencyCard(EligibilityVerificationForm): 

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

147 

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 ) 

172 

173 

174class MSTCourtesyCard(EligibilityVerificationForm): 

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

176 

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 ) 

201 

202 

203class SBMTDMobilityPass(EligibilityVerificationForm): 

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

205 

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 )