Coverage for benefits/in_person/views.py: 98%

107 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-19 00:56 +0000

1import logging 

2 

3from django.contrib.admin import site as admin_site 

4from django.http import JsonResponse 

5from django.template.response import TemplateResponse 

6from django.shortcuts import redirect 

7from django.urls import reverse 

8import sentry_sdk 

9 

10 

11from benefits.routes import routes 

12from benefits.core import models, session 

13from benefits.eligibility import analytics as eligibility_analytics 

14from benefits.enrollment import analytics as enrollment_analytics 

15from benefits.enrollment.enrollment import Status, request_card_tokenization_access, enroll 

16 

17from benefits.in_person import forms 

18 

19logger = logging.getLogger(__name__) 

20 

21 

22def eligibility(request): 

23 """View handler for the in-person eligibility flow selection form.""" 

24 

25 agency = session.agency(request) 

26 context = { 

27 **admin_site.each_context(request), 

28 "form": forms.InPersonEligibilityForm(agency=agency), 

29 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

30 } 

31 

32 if request.method == "POST": 

33 form = forms.InPersonEligibilityForm(data=request.POST, agency=agency) 

34 

35 if form.is_valid(): 

36 flow_id = form.cleaned_data.get("flow") 

37 flow = models.EnrollmentFlow.objects.get(id=flow_id) 

38 session.update(request, flow=flow) 

39 eligibility_analytics.selected_flow(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON) 

40 eligibility_analytics.started_eligibility(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON) 

41 

42 in_person_enrollment = reverse(routes.IN_PERSON_ENROLLMENT) 

43 response = redirect(in_person_enrollment) 

44 else: 

45 context["form"] = form 

46 response = TemplateResponse(request, "in_person/eligibility.html", context) 

47 else: 

48 response = TemplateResponse(request, "in_person/eligibility.html", context) 

49 

50 return response 

51 

52 

53def token(request): 

54 """View handler for the enrollment auth token.""" 

55 if not session.enrollment_token_valid(request): 

56 response = request_card_tokenization_access(request) 

57 

58 if response.status is Status.SUCCESS: 

59 session.update(request, enrollment_token=response.access_token, enrollment_token_exp=response.expires_at) 

60 elif response.status is Status.SYSTEM_ERROR or response.status is Status.EXCEPTION: 60 ↛ 75line 60 didn't jump to line 75 because the condition on line 60 was always true

61 logger.debug("Error occurred while requesting access token", exc_info=response.exception) 

62 sentry_sdk.capture_exception(response.exception) 

63 enrollment_analytics.failed_access_token_request( 

64 request, response.status_code, enrollment_method=models.EnrollmentMethods.IN_PERSON 

65 ) 

66 

67 if response.status is Status.SYSTEM_ERROR: 

68 redirect = reverse(routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR) 

69 else: 

70 redirect = reverse(routes.IN_PERSON_SERVER_ERROR) 

71 

72 data = {"redirect": redirect} 

73 return JsonResponse(data) 

74 

75 data = {"token": session.enrollment_token(request)} 

76 

77 return JsonResponse(data) 

78 

79 

80def enrollment(request): 

81 """View handler for the in-person enrollment page.""" 

82 # POST back after transit processor form, process card token 

83 if request.method == "POST": 

84 form = forms.CardTokenizeSuccessForm(request.POST) 

85 if not form.is_valid(): 

86 raise Exception("Invalid card token form") 

87 

88 flow = session.flow(request) 

89 eligibility_analytics.returned_success(request, flow, enrollment_method=models.EnrollmentMethods.IN_PERSON) 

90 card_token = form.cleaned_data.get("card_token") 

91 status, exception = enroll(request, card_token) 

92 

93 match (status): 

94 case Status.SUCCESS: 

95 agency = session.agency(request) 

96 expiry = session.enrollment_expiry(request) 

97 verified_by = f"{request.user.first_name} {request.user.last_name}" 

98 event = models.EnrollmentEvent.objects.create( 

99 transit_agency=agency, 

100 enrollment_flow=flow, 

101 enrollment_method=models.EnrollmentMethods.IN_PERSON, 

102 verified_by=verified_by, 

103 expiration_datetime=expiry, 

104 ) 

105 event.save() 

106 enrollment_analytics.returned_success( 

107 request, flow.group_id, enrollment_method=models.EnrollmentMethods.IN_PERSON 

108 ) 

109 return redirect(routes.IN_PERSON_ENROLLMENT_SUCCESS) 

110 

111 case Status.SYSTEM_ERROR: 

112 enrollment_analytics.returned_error( 

113 request, str(exception), enrollment_method=models.EnrollmentMethods.IN_PERSON 

114 ) 

115 sentry_sdk.capture_exception(exception) 

116 return redirect(routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR) 

117 

118 case Status.EXCEPTION: 

119 enrollment_analytics.returned_error( 

120 request, str(exception), enrollment_method=models.EnrollmentMethods.IN_PERSON 

121 ) 

122 sentry_sdk.capture_exception(exception) 

123 return redirect(routes.IN_PERSON_SERVER_ERROR) 

124 

125 case Status.REENROLLMENT_ERROR: 125 ↛ exitline 125 didn't return from function 'enrollment' because the pattern on line 125 always matched

126 enrollment_analytics.returned_error( 

127 request, "Re-enrollment error.", enrollment_method=models.EnrollmentMethods.IN_PERSON 

128 ) 

129 return redirect(routes.IN_PERSON_ENROLLMENT_REENROLLMENT_ERROR) 

130 # GET enrollment index 

131 else: 

132 agency = session.agency(request) 

133 

134 tokenize_retry_form = forms.CardTokenizeFailForm(routes.IN_PERSON_ENROLLMENT_RETRY, "form-card-tokenize-fail-retry") 

135 tokenize_server_error_form = forms.CardTokenizeFailForm( 

136 routes.IN_PERSON_SERVER_ERROR, "form-card-tokenize-fail-server-error" 

137 ) 

138 tokenize_system_error_form = forms.CardTokenizeFailForm( 

139 routes.IN_PERSON_ENROLLMENT_SYSTEM_ERROR, "form-card-tokenize-fail-system-error" 

140 ) 

141 tokenize_success_form = forms.CardTokenizeSuccessForm( 

142 action_url=routes.IN_PERSON_ENROLLMENT, auto_id=True, label_suffix="" 

143 ) 

144 

145 context = { 

146 **admin_site.each_context(request), 

147 "forms": [tokenize_retry_form, tokenize_server_error_form, tokenize_system_error_form, tokenize_success_form], 

148 "cta_button": "tokenize_card", 

149 "card_tokenize_env": agency.transit_processor.card_tokenize_env, 

150 "card_tokenize_func": agency.transit_processor.card_tokenize_func, 

151 "card_tokenize_url": agency.transit_processor.card_tokenize_url, 

152 "enrollment_method": models.EnrollmentMethods.IN_PERSON, 

153 "token_field": "card_token", 

154 "form_retry": tokenize_retry_form.id, 

155 "form_server_error": tokenize_server_error_form.id, 

156 "form_success": tokenize_success_form.id, 

157 "form_system_error": tokenize_system_error_form.id, 

158 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

159 } 

160 

161 return TemplateResponse(request, "in_person/enrollment/index.html", context) 

162 

163 

164def reenrollment_error(request): 

165 """View handler for a re-enrollment attempt that is not yet within the re-enrollment window.""" 

166 

167 agency = session.agency(request) 

168 context = { 

169 **admin_site.each_context(request), 

170 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

171 } 

172 

173 flow = session.flow(request) 

174 context["flow_label"] = flow.label 

175 

176 return TemplateResponse(request, "in_person/enrollment/reenrollment_error.html", context) 

177 

178 

179def retry(request): 

180 """View handler for card verification failure.""" 

181 # enforce POST-only route for sending analytics 

182 if request.method == "POST": 

183 enrollment_analytics.returned_retry(request, enrollment_method=models.EnrollmentMethods.IN_PERSON) 

184 

185 agency = session.agency(request) 

186 context = { 

187 **admin_site.each_context(request), 

188 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

189 } 

190 

191 return TemplateResponse(request, "in_person/enrollment/retry.html", context) 

192 

193 

194def system_error(request): 

195 """View handler for an enrollment system error.""" 

196 agency = session.agency(request) 

197 context = { 

198 **admin_site.each_context(request), 

199 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

200 } 

201 

202 return TemplateResponse(request, "in_person/enrollment/system_error.html", context) 

203 

204 

205def server_error(request): 

206 """View handler for errors caused by a misconfiguration or bad request.""" 

207 agency = session.agency(request) 

208 context = { 

209 **admin_site.each_context(request), 

210 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

211 } 

212 

213 return TemplateResponse(request, "in_person/enrollment/server_error.html", context) 

214 

215 

216def success(request): 

217 """View handler for the final success page.""" 

218 agency = session.agency(request) 

219 context = { 

220 **admin_site.each_context(request), 

221 "title": f"{agency.long_name} | In-person enrollment | {admin_site.site_title}", 

222 } 

223 

224 return TemplateResponse(request, "in_person/enrollment/success.html", context)